smartest 0.6.0 → 0.6.2.alpha1
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/CHANGELOG.md +13 -0
- data/README.md +27 -10
- data/lib/smartest/init_browser_generator.rb +41 -9
- data/lib/smartest/init_rails_generator.rb +47 -15
- data/lib/smartest/version.rb +1 -1
- data/sig/smartest.rbs +163 -0
- data/smartest/smartest_test.rb +210 -1
- data/smartest.gemspec +1 -0
- metadata +5 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5eb327b86d510c4cf4e8ebdf31fcd7be3fe1b78c9109528ac99af08c3af1f9e4
|
|
4
|
+
data.tar.gz: 7937fde33ac1e62adb5f4bc39b54b938138af915008fcc350742f66420df5848
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8b011cea66dfec275fe790c0ced127819c23a18e70878bb9f4519d0e87b05e47c06b2b7bbc5de771ff3782cbb032409cb57be50ca2a2211fe79150a15a46b224
|
|
7
|
+
data.tar.gz: a77eb822acc8bb07f4f3b38a5f09bf3ca573fabb4542bc03b2e49120b110aad749042fe8004e38c733b0f4629f77673c371011382d7ab2d5e0881364c7a48595
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.1
|
|
4
|
+
|
|
5
|
+
### Bug Fixes
|
|
6
|
+
|
|
7
|
+
- Fix Rails Docker scaffold friction in `smartest --init-rails` and the
|
|
8
|
+
generated Playwright fixtures so the Docker-based browser test setup works
|
|
9
|
+
out of the box.
|
|
10
|
+
|
|
11
|
+
### Documentation
|
|
12
|
+
|
|
13
|
+
- Document fresh Rails database preparation for browser tests, including the
|
|
14
|
+
Docker-based workflow.
|
|
15
|
+
|
|
3
16
|
## 0.6.0
|
|
4
17
|
|
|
5
18
|
### New Features
|
data/README.md
CHANGED
|
@@ -227,11 +227,11 @@ smartest/matchers/playwright_matcher.rb
|
|
|
227
227
|
smartest/example_browser_test.rb
|
|
228
228
|
```
|
|
229
229
|
|
|
230
|
-
It also registers `PlaywrightFixture` and `PlaywrightMatcher`, adds
|
|
231
|
-
`playwright-ruby-client` to the Gemfile test
|
|
232
|
-
`npm init --yes` when no `package.json`
|
|
233
|
-
`npm install playwright --save-dev`, and downloads Chromium
|
|
234
|
-
`./node_modules/.bin/playwright install`.
|
|
230
|
+
It also registers `PlaywrightFixture` and `PlaywrightMatcher`, keeps or adds
|
|
231
|
+
`smartest` in the Gemfile, adds `playwright-ruby-client` to the Gemfile test
|
|
232
|
+
group, runs `bundle install`, runs `npm init --yes` when no `package.json`
|
|
233
|
+
exists yet, runs `npm install playwright --save-dev`, and downloads Chromium
|
|
234
|
+
with `./node_modules/.bin/playwright install`.
|
|
235
235
|
|
|
236
236
|
Run the generated browser example with:
|
|
237
237
|
|
|
@@ -239,6 +239,9 @@ Run the generated browser example with:
|
|
|
239
239
|
bundle exec smartest smartest/example_browser_test.rb
|
|
240
240
|
```
|
|
241
241
|
|
|
242
|
+
The generated Playwright examples include `# @type [Playwright::Page] page`
|
|
243
|
+
before the test block so RubyMine can complete methods on the `page` fixture.
|
|
244
|
+
|
|
242
245
|
## Rails browser quick start
|
|
243
246
|
|
|
244
247
|
Initialize a Rails browser-test scaffold:
|
|
@@ -256,11 +259,15 @@ smartest/matchers/playwright_matcher.rb
|
|
|
256
259
|
smartest/example_rails_system_test.rb
|
|
257
260
|
```
|
|
258
261
|
|
|
259
|
-
The generated fixture requires `smartest/rails
|
|
262
|
+
The generated fixture requires `smartest/rails`, loads `config/environment`
|
|
263
|
+
when `test_helper` requires the fixture file, and starts
|
|
260
264
|
`Smartest::Rails::TestServer` against `Rails.application` in the same Ruby
|
|
261
|
-
process as the test runner.
|
|
262
|
-
|
|
263
|
-
|
|
265
|
+
process as the test runner. Loading Rails during helper setup makes app
|
|
266
|
+
constants such as ActiveRecord models available inside test files and
|
|
267
|
+
`around_test` hooks before per-test fixtures are resolved. The generated
|
|
268
|
+
fixture forces `RAILS_ENV` and `RACK_ENV` to `test` before Rails boots.
|
|
269
|
+
`Smartest::Rails::TestServer` is only loaded by explicitly requiring
|
|
270
|
+
`smartest/rails`; plain `require "smartest"` does not load Puma.
|
|
264
271
|
|
|
265
272
|
This is aimed at local Rails system tests that combine Rails test data, stubs,
|
|
266
273
|
and Playwright browser assertions. It is not a Capybara compatibility layer or
|
|
@@ -282,7 +289,13 @@ SMARTEST_SKIP_BROWSER_DOWNLOAD=1 bundle exec smartest --init-rails
|
|
|
282
289
|
At runtime, set `PLAYWRIGHT_WS_ENDPOINT`,
|
|
283
290
|
`SMARTEST_RAILS_TEST_SERVER_HOST`, `SMARTEST_RAILS_TEST_SERVER_PORT`, and
|
|
284
291
|
`SMARTEST_RAILS_BASE_URL` so the generated fixture connects to the Playwright
|
|
285
|
-
sidecar and gives the browser a Docker-network URL for Rails.
|
|
292
|
+
sidecar and gives the browser a Docker-network URL for Rails. These are usually
|
|
293
|
+
stable Docker topology settings, so put them in `compose.yml` instead of
|
|
294
|
+
repeating them on every `docker compose run` command.
|
|
295
|
+
For a Rails Compose service named `web`, use
|
|
296
|
+
`SMARTEST_RAILS_BASE_URL=http://web:4001`; replace `web` with your service name.
|
|
297
|
+
The generated Rails fixture sets `RAILS_ENV` and `RACK_ENV` to `test`, even if
|
|
298
|
+
the same service normally runs in development.
|
|
286
299
|
|
|
287
300
|
Run the generated Rails browser example with:
|
|
288
301
|
|
|
@@ -318,6 +331,10 @@ end
|
|
|
318
331
|
|
|
319
332
|
This makes fixture usage explicit and avoids relying on positional argument order.
|
|
320
333
|
|
|
334
|
+
Smartest also ships RBS signatures for the public DSL, including `test`,
|
|
335
|
+
`around_suite`, `around_test`, `fixture`, `suite_fixture`, `on_teardown`,
|
|
336
|
+
`expect`, and hook registration methods such as `use_fixture`.
|
|
337
|
+
|
|
321
338
|
## Skipping and pending tests
|
|
322
339
|
|
|
323
340
|
Use `skip` at the start of a test when the rest of the body should not run:
|
|
@@ -63,6 +63,7 @@ module Smartest
|
|
|
63
63
|
|
|
64
64
|
require "test_helper"
|
|
65
65
|
|
|
66
|
+
# @type [Playwright::Page] page
|
|
66
67
|
test("finds the smartest gem on RubyGems") do |page:|
|
|
67
68
|
page.goto("https://rubygems.org/")
|
|
68
69
|
page.locator("input[name='query']").fill("smartest")
|
|
@@ -147,24 +148,45 @@ module Smartest
|
|
|
147
148
|
path = File.join(@root, "Gemfile")
|
|
148
149
|
exists = File.exist?(path)
|
|
149
150
|
contents = exists ? File.read(path) : "source \"https://rubygems.org\"\n"
|
|
151
|
+
updated = contents.dup
|
|
150
152
|
|
|
151
|
-
|
|
153
|
+
unless gem_present?(updated, "smartest")
|
|
154
|
+
updated = append_gem(updated, 'gem "smartest"')
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
if gem_present?(updated, "playwright-ruby-client")
|
|
152
158
|
@output.puts "exist Gemfile playwright-ruby-client"
|
|
153
|
-
|
|
159
|
+
else
|
|
160
|
+
updated = append_gem(updated, 'gem "playwright-ruby-client", group: :test')
|
|
154
161
|
end
|
|
155
162
|
|
|
163
|
+
if updated != contents
|
|
164
|
+
File.write(path, updated)
|
|
165
|
+
@output.puts(exists ? "update Gemfile" : "create Gemfile")
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def append_gem(contents, line)
|
|
156
170
|
separator = contents.end_with?("\n") ? "" : "\n"
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
171
|
+
"#{contents}#{separator}\n#{line}\n"
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def gem_present?(contents, name)
|
|
175
|
+
contents.each_line.any? do |line|
|
|
176
|
+
line.match?(/\A\s*gem\s+["']#{Regexp.escape(name)}["']/)
|
|
177
|
+
end
|
|
160
178
|
end
|
|
161
179
|
|
|
162
180
|
def install_dependencies
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
181
|
+
commands = install_commands
|
|
182
|
+
|
|
183
|
+
with_unbundled_env do
|
|
184
|
+
commands.each do |command|
|
|
185
|
+
@output.puts "run #{command.join(" ")}"
|
|
186
|
+
next if @command_runner.call(command, chdir: @root)
|
|
166
187
|
|
|
167
|
-
|
|
188
|
+
raise "command failed: #{command.join(" ")}"
|
|
189
|
+
end
|
|
168
190
|
end
|
|
169
191
|
end
|
|
170
192
|
|
|
@@ -179,5 +201,15 @@ module Smartest
|
|
|
179
201
|
def run_system_command(command, chdir:)
|
|
180
202
|
system(*command, chdir: chdir)
|
|
181
203
|
end
|
|
204
|
+
|
|
205
|
+
def with_unbundled_env(&block)
|
|
206
|
+
require "bundler"
|
|
207
|
+
|
|
208
|
+
if Bundler.respond_to?(:with_unbundled_env)
|
|
209
|
+
Bundler.with_unbundled_env(&block)
|
|
210
|
+
else
|
|
211
|
+
Bundler.with_clean_env(&block)
|
|
212
|
+
end
|
|
213
|
+
end
|
|
182
214
|
end
|
|
183
215
|
end
|
|
@@ -10,14 +10,14 @@ module Smartest
|
|
|
10
10
|
require 'smartest/rails'
|
|
11
11
|
require "playwright"
|
|
12
12
|
|
|
13
|
+
# Force the test environment and load Rails while test_helper is required
|
|
14
|
+
# so app constants are available before per-test fixtures are resolved.
|
|
15
|
+
ENV["RAILS_ENV"] = "test"
|
|
16
|
+
ENV["RACK_ENV"] = "test"
|
|
17
|
+
require_relative "../../config/environment"
|
|
18
|
+
|
|
13
19
|
class RailsSystemTestFixture < Smartest::Fixture
|
|
14
20
|
suite_fixture :rails_server do
|
|
15
|
-
# Set the environment before loading config/environment so the test
|
|
16
|
-
# server cannot boot against the development database by default.
|
|
17
|
-
ENV["RAILS_ENV"] ||= "test"
|
|
18
|
-
ENV["RACK_ENV"] ||= ENV["RAILS_ENV"]
|
|
19
|
-
require_relative "../../config/environment"
|
|
20
|
-
|
|
21
21
|
server = Smartest::Rails::TestServer.new(
|
|
22
22
|
app: Rails.application,
|
|
23
23
|
host: ENV["SMARTEST_RAILS_TEST_SERVER_HOST"],
|
|
@@ -118,6 +118,7 @@ module Smartest
|
|
|
118
118
|
|
|
119
119
|
require "test_helper"
|
|
120
120
|
|
|
121
|
+
# @type [Playwright::Page] page
|
|
121
122
|
test("loads the Rails application") do |page:|
|
|
122
123
|
response = page.goto("/")
|
|
123
124
|
|
|
@@ -198,24 +199,45 @@ module Smartest
|
|
|
198
199
|
path = File.join(@root, "Gemfile")
|
|
199
200
|
exists = File.exist?(path)
|
|
200
201
|
contents = exists ? File.read(path) : "source \"https://rubygems.org\"\n"
|
|
202
|
+
updated = contents.dup
|
|
201
203
|
|
|
202
|
-
|
|
204
|
+
unless gem_present?(updated, "smartest")
|
|
205
|
+
updated = append_gem(updated, 'gem "smartest"')
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
if gem_present?(updated, "playwright-ruby-client")
|
|
203
209
|
@output.puts "exist Gemfile playwright-ruby-client"
|
|
204
|
-
|
|
210
|
+
else
|
|
211
|
+
updated = append_gem(updated, 'gem "playwright-ruby-client", group: :test')
|
|
205
212
|
end
|
|
206
213
|
|
|
214
|
+
if updated != contents
|
|
215
|
+
File.write(path, updated)
|
|
216
|
+
@output.puts(exists ? "update Gemfile" : "create Gemfile")
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def append_gem(contents, line)
|
|
207
221
|
separator = contents.end_with?("\n") ? "" : "\n"
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
222
|
+
"#{contents}#{separator}\n#{line}\n"
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def gem_present?(contents, name)
|
|
226
|
+
contents.each_line.any? do |line|
|
|
227
|
+
line.match?(/\A\s*gem\s+["']#{Regexp.escape(name)}["']/)
|
|
228
|
+
end
|
|
211
229
|
end
|
|
212
230
|
|
|
213
231
|
def install_dependencies
|
|
214
|
-
|
|
215
|
-
@output.puts "run #{command.join(" ")}"
|
|
216
|
-
next if @command_runner.call(command, chdir: @root)
|
|
232
|
+
commands = install_commands
|
|
217
233
|
|
|
218
|
-
|
|
234
|
+
with_unbundled_env do
|
|
235
|
+
commands.each do |command|
|
|
236
|
+
@output.puts "run #{command.join(" ")}"
|
|
237
|
+
next if @command_runner.call(command, chdir: @root)
|
|
238
|
+
|
|
239
|
+
raise "command failed: #{command.join(" ")}"
|
|
240
|
+
end
|
|
219
241
|
end
|
|
220
242
|
|
|
221
243
|
if skip_browser_download?
|
|
@@ -238,5 +260,15 @@ module Smartest
|
|
|
238
260
|
def run_system_command(command, chdir:)
|
|
239
261
|
system(*command, chdir: chdir)
|
|
240
262
|
end
|
|
263
|
+
|
|
264
|
+
def with_unbundled_env(&block)
|
|
265
|
+
require "bundler"
|
|
266
|
+
|
|
267
|
+
if Bundler.respond_to?(:with_unbundled_env)
|
|
268
|
+
Bundler.with_unbundled_env(&block)
|
|
269
|
+
else
|
|
270
|
+
Bundler.with_clean_env(&block)
|
|
271
|
+
end
|
|
272
|
+
end
|
|
241
273
|
end
|
|
242
274
|
end
|
data/lib/smartest/version.rb
CHANGED
data/sig/smartest.rbs
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Smartest public DSL signatures for editors and type-aware tooling.
|
|
2
|
+
|
|
3
|
+
module Smartest
|
|
4
|
+
VERSION: String
|
|
5
|
+
|
|
6
|
+
def self.suite: () -> Suite
|
|
7
|
+
def self.reset!: () -> Suite
|
|
8
|
+
def self.disable_autorun!: () -> true
|
|
9
|
+
def self.autorun_disabled?: () -> bool
|
|
10
|
+
def self.register_autorun!: () -> nil
|
|
11
|
+
def self.install_dsl!: () -> untyped
|
|
12
|
+
def self.fatal_exception?: (Exception) -> bool
|
|
13
|
+
|
|
14
|
+
module DSL
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
# Define a named test. Fixture values are requested from the block with
|
|
18
|
+
# required keyword arguments, for example `do |page:|`.
|
|
19
|
+
def test: (String | Symbol, **untyped) { (*untyped, **untyped) -> untyped } -> void
|
|
20
|
+
|
|
21
|
+
# Wrap the whole suite. The block receives a run target and must call
|
|
22
|
+
# `suite.run` exactly once.
|
|
23
|
+
def around_suite: () { (SuiteRun) -> untyped } -> void
|
|
24
|
+
|
|
25
|
+
# Wrap tests registered after this hook in the same file. The block receives
|
|
26
|
+
# a run target and must call `test.run` exactly once.
|
|
27
|
+
def around_test: () { (TestRun) -> untyped } -> void
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
module Expectations
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def expect: (?untyped) ?{ () -> untyped } -> ExpectationTarget
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
module Matchers
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def eq: (untyped) -> Matcher
|
|
40
|
+
def include: (untyped) -> Matcher
|
|
41
|
+
def start_with: (*untyped) -> Matcher
|
|
42
|
+
def end_with: (*untyped) -> Matcher
|
|
43
|
+
def be_a: (Class | Module) -> Matcher
|
|
44
|
+
def be_an: (Class | Module) -> Matcher
|
|
45
|
+
def be_nil: () -> Matcher
|
|
46
|
+
def match: (Regexp | String) -> Matcher
|
|
47
|
+
def contain_exactly: (*untyped) -> Matcher
|
|
48
|
+
def match_array: (Array[untyped]) -> Matcher
|
|
49
|
+
def raise_error: (*untyped) -> Matcher
|
|
50
|
+
def change: () { () -> untyped } -> Matcher
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
module ConstantStubHelpers
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def with_stub_const: (String | Symbol, untyped) { () -> untyped } -> untyped
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
class Fixture
|
|
60
|
+
# Define a test-scoped fixture by default. Fixture dependencies are requested
|
|
61
|
+
# from the block with required keyword arguments.
|
|
62
|
+
def self.fixture: (String | Symbol, ?scope: Symbol) { (*untyped, **untyped) -> untyped } -> FixtureDefinition
|
|
63
|
+
|
|
64
|
+
# Define a suite-scoped fixture shared by all tests in the suite.
|
|
65
|
+
def self.suite_fixture: (String | Symbol) { (*untyped, **untyped) -> untyped } -> FixtureDefinition
|
|
66
|
+
|
|
67
|
+
def self.fixture_definitions: () -> Hash[Symbol, FixtureDefinition]
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
def on_teardown: () { () -> untyped } -> untyped
|
|
72
|
+
def simple_stub_any_instance_of: (Class | Module, String | Symbol) { (*untyped, **untyped) -> untyped } -> SimpleStub
|
|
73
|
+
def simple_stub: (untyped, String | Symbol) { (*untyped, **untyped) -> untyped } -> SimpleStub
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
class AroundSuiteContext
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
def use_fixture: (Class | Module) -> untyped
|
|
80
|
+
def use_matcher: (Module) -> untyped
|
|
81
|
+
def around_test: () { (TestRun) -> untyped } -> void
|
|
82
|
+
def with_stub_const: (String | Symbol, untyped) { () -> untyped } -> untyped
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
class AroundTestContext
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
def use_fixture: (Class | Module) -> untyped
|
|
89
|
+
def use_matcher: (Module) -> untyped
|
|
90
|
+
def use_helper: (Module) -> untyped
|
|
91
|
+
def skip: (?String) -> void
|
|
92
|
+
def pending: (?String) -> void
|
|
93
|
+
def with_stub_const: (String | Symbol, untyped) { () -> untyped } -> untyped
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
class ExecutionContext
|
|
97
|
+
include Expectations
|
|
98
|
+
include Matchers
|
|
99
|
+
include ConstantStubHelpers
|
|
100
|
+
|
|
101
|
+
private
|
|
102
|
+
|
|
103
|
+
def skip: (?String) -> void
|
|
104
|
+
def pending: (?String) -> void
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
class SuiteRun
|
|
108
|
+
attr_reader result: untyped
|
|
109
|
+
|
|
110
|
+
def run: () -> untyped
|
|
111
|
+
def ran?: () -> bool
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
class TestRun
|
|
115
|
+
attr_reader result: untyped
|
|
116
|
+
|
|
117
|
+
def run: () -> untyped
|
|
118
|
+
def ran?: () -> bool
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
class ExpectationTarget
|
|
122
|
+
def to: (untyped) -> self
|
|
123
|
+
def not_to: (untyped) -> self
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
class Matcher
|
|
127
|
+
def and: (untyped) -> Matcher
|
|
128
|
+
def or: (untyped) -> Matcher
|
|
129
|
+
def description: () -> String
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
class FixtureDefinition
|
|
133
|
+
attr_reader name: Symbol
|
|
134
|
+
attr_reader block: Proc
|
|
135
|
+
attr_reader location: Thread::Backtrace::Location?
|
|
136
|
+
attr_reader scope: Symbol
|
|
137
|
+
attr_reader dependencies: Array[Symbol]
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
class SimpleStub
|
|
141
|
+
def apply: () -> self
|
|
142
|
+
def reset: () -> nil
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
class Suite
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
module Kernel
|
|
150
|
+
private
|
|
151
|
+
|
|
152
|
+
# Define a named Smartest test. Fixture values are requested with keyword
|
|
153
|
+
# block parameters, for example `test("opens page") do |page:|`.
|
|
154
|
+
def test: (String | Symbol, **untyped) { (*untyped, **untyped) -> untyped } -> void
|
|
155
|
+
|
|
156
|
+
# Register a suite hook. The block receives a run target and must call
|
|
157
|
+
# `suite.run` exactly once.
|
|
158
|
+
def around_suite: () { (Smartest::SuiteRun) -> untyped } -> void
|
|
159
|
+
|
|
160
|
+
# Register a test hook for tests declared after this hook in the same file.
|
|
161
|
+
# The block receives a run target and must call `test.run` exactly once.
|
|
162
|
+
def around_test: () { (Smartest::TestRun) -> untyped } -> void
|
|
163
|
+
end
|
data/smartest/smartest_test.rb
CHANGED
|
@@ -82,6 +82,12 @@ test("registers fixture classes with use_fixture") do |registered_user_name:|
|
|
|
82
82
|
expect(registered_user_name).to eq("Alice")
|
|
83
83
|
end
|
|
84
84
|
|
|
85
|
+
test("gemspec packages RBS signatures") do
|
|
86
|
+
spec = Gem::Specification.load(File.expand_path("../smartest.gemspec", __dir__))
|
|
87
|
+
|
|
88
|
+
expect(spec.files).to include("sig/smartest.rbs")
|
|
89
|
+
end
|
|
90
|
+
|
|
85
91
|
test("runs a registered test") do
|
|
86
92
|
suite = Smartest::Suite.new
|
|
87
93
|
suite.tests.add(SmartestSelfTest.test_case("factorial", proc { expect(1 * 2 * 3).to eq(6) }))
|
|
@@ -2150,6 +2156,7 @@ test("cli browser init generator creates Playwright scaffold and installation co
|
|
|
2150
2156
|
expect(status).to eq(0)
|
|
2151
2157
|
example_browser_test = File.read(File.join(dir, "smartest/example_browser_test.rb"))
|
|
2152
2158
|
expect(example_browser_test).to include("finds the smartest gem on RubyGems")
|
|
2159
|
+
expect(example_browser_test).to include("# @type [Playwright::Page] page")
|
|
2153
2160
|
expect(example_browser_test).to include('expect(page).to have_url("https://rubygems.org/gems/smartest")')
|
|
2154
2161
|
expect(example_browser_test).to include('expect(page.locator("h1")).to have_text("smartest")')
|
|
2155
2162
|
expect(example_browser_test).not_to include("0.3.0.alpha1")
|
|
@@ -2166,6 +2173,8 @@ test("cli browser init generator creates Playwright scaffold and installation co
|
|
|
2166
2173
|
expect(helper_contents).to include("use_matcher PredicateMatcher\n use_fixture PlaywrightFixture\n use_matcher PlaywrightMatcher\n suite.run")
|
|
2167
2174
|
|
|
2168
2175
|
gemfile_contents = File.read(File.join(dir, "Gemfile"))
|
|
2176
|
+
expect(gemfile_contents).to include('gem "smartest"')
|
|
2177
|
+
expect(gemfile_contents.scan(/^\s*gem ["']smartest["']/).length).to eq(1)
|
|
2169
2178
|
expect(gemfile_contents).to include('gem "playwright-ruby-client", group: :test')
|
|
2170
2179
|
expect(commands).to eq(
|
|
2171
2180
|
[
|
|
@@ -2183,6 +2192,70 @@ test("cli browser init generator creates Playwright scaffold and installation co
|
|
|
2183
2192
|
end
|
|
2184
2193
|
end
|
|
2185
2194
|
|
|
2195
|
+
test("cli browser init generator keeps smartest in Gemfile when adding Playwright") do
|
|
2196
|
+
Dir.mktmpdir do |dir|
|
|
2197
|
+
File.write(File.join(dir, "Gemfile"), <<~RUBY)
|
|
2198
|
+
source "https://rubygems.org"
|
|
2199
|
+
RUBY
|
|
2200
|
+
|
|
2201
|
+
generator = Smartest::InitBrowserGenerator.new(
|
|
2202
|
+
root: dir,
|
|
2203
|
+
output: StringIO.new,
|
|
2204
|
+
command_runner: ->(_command, chdir:) { true }
|
|
2205
|
+
)
|
|
2206
|
+
|
|
2207
|
+
status = generator.run
|
|
2208
|
+
|
|
2209
|
+
expect(status).to eq(0)
|
|
2210
|
+
gemfile_contents = File.read(File.join(dir, "Gemfile"))
|
|
2211
|
+
expect(gemfile_contents).to include('gem "smartest"')
|
|
2212
|
+
expect(gemfile_contents).to include('gem "playwright-ruby-client", group: :test')
|
|
2213
|
+
end
|
|
2214
|
+
end
|
|
2215
|
+
|
|
2216
|
+
test("cli browser init generator runs installation commands outside the current Bundler environment") do
|
|
2217
|
+
require "bundler"
|
|
2218
|
+
|
|
2219
|
+
Dir.mktmpdir do |dir|
|
|
2220
|
+
File.write(File.join(dir, "Gemfile"), <<~RUBY)
|
|
2221
|
+
source "https://rubygems.org"
|
|
2222
|
+
|
|
2223
|
+
gem "smartest"
|
|
2224
|
+
RUBY
|
|
2225
|
+
|
|
2226
|
+
command_environments = []
|
|
2227
|
+
output = StringIO.new
|
|
2228
|
+
generator = Smartest::InitBrowserGenerator.new(
|
|
2229
|
+
root: dir,
|
|
2230
|
+
output: output,
|
|
2231
|
+
command_runner: ->(_command, chdir:) {
|
|
2232
|
+
command_environments << {
|
|
2233
|
+
bundle_gemfile: ENV["BUNDLE_GEMFILE"],
|
|
2234
|
+
bundle_bin_path: ENV["BUNDLE_BIN_PATH"],
|
|
2235
|
+
rubyopt: ENV["RUBYOPT"]
|
|
2236
|
+
}
|
|
2237
|
+
true
|
|
2238
|
+
}
|
|
2239
|
+
)
|
|
2240
|
+
|
|
2241
|
+
SmartestSelfTest.with_env(
|
|
2242
|
+
"BUNDLE_GEMFILE" => File.join(dir, "Gemfile"),
|
|
2243
|
+
"BUNDLE_BIN_PATH" => "/tmp/smartest-self-test-bundle",
|
|
2244
|
+
"RUBYOPT" => "-rbundler/setup -W0"
|
|
2245
|
+
) do
|
|
2246
|
+
status = generator.run
|
|
2247
|
+
expect(status).to eq(0)
|
|
2248
|
+
end
|
|
2249
|
+
|
|
2250
|
+
expect(command_environments.length).to eq(4)
|
|
2251
|
+
expect(command_environments.all? do |environment|
|
|
2252
|
+
environment[:bundle_gemfile].nil? &&
|
|
2253
|
+
environment[:bundle_bin_path].nil? &&
|
|
2254
|
+
!environment[:rubyopt].to_s.include?("bundler/setup")
|
|
2255
|
+
end).to eq(true)
|
|
2256
|
+
end
|
|
2257
|
+
end
|
|
2258
|
+
|
|
2186
2259
|
test("cli browser init generator skips npm init when package.json already exists") do
|
|
2187
2260
|
Dir.mktmpdir do |dir|
|
|
2188
2261
|
File.write(File.join(dir, "Gemfile"), <<~RUBY)
|
|
@@ -2341,8 +2414,12 @@ test("cli rails init generator creates Rails browser scaffold and installation c
|
|
|
2341
2414
|
expect(rails_fixture).to include("require 'smartest/rails'")
|
|
2342
2415
|
expect(rails_fixture).to include("class RailsSystemTestFixture < Smartest::Fixture")
|
|
2343
2416
|
expect(rails_fixture).to include("suite_fixture :rails_server")
|
|
2344
|
-
expect(rails_fixture).to include("
|
|
2417
|
+
expect(rails_fixture).to include('ENV["RAILS_ENV"] = "test"')
|
|
2418
|
+
expect(rails_fixture).to include('ENV["RACK_ENV"] = "test"')
|
|
2419
|
+
expect(rails_fixture).not_to include('ENV["RAILS_ENV"] ||=')
|
|
2420
|
+
expect(rails_fixture).to include("constants are available before per-test fixtures are resolved")
|
|
2345
2421
|
expect(rails_fixture).to include('require_relative "../../config/environment"')
|
|
2422
|
+
expect(rails_fixture.index('require_relative "../../config/environment"') < rails_fixture.index("class RailsSystemTestFixture")).to eq(true)
|
|
2346
2423
|
expect(rails_fixture).to include("Smartest::Rails::TestServer.new(")
|
|
2347
2424
|
expect(rails_fixture).to include('host: ENV["SMARTEST_RAILS_TEST_SERVER_HOST"]')
|
|
2348
2425
|
expect(rails_fixture).not_to include("bind_host:")
|
|
@@ -2376,6 +2453,7 @@ test("cli rails init generator creates Rails browser scaffold and installation c
|
|
|
2376
2453
|
expect(rails_fixture).to include("fixture :page do |browser_context:|")
|
|
2377
2454
|
|
|
2378
2455
|
example_test = File.read(File.join(dir, "smartest/example_rails_system_test.rb"))
|
|
2456
|
+
expect(example_test).to include("# @type [Playwright::Page] page")
|
|
2379
2457
|
expect(example_test).to include('test("loads the Rails application") do |page:|')
|
|
2380
2458
|
expect(example_test).to include('response = page.goto("/")')
|
|
2381
2459
|
expect(example_test).to include("expect(response.status).to be_between(200, 599)")
|
|
@@ -2385,6 +2463,8 @@ test("cli rails init generator creates Rails browser scaffold and installation c
|
|
|
2385
2463
|
expect(helper_contents).not_to include("Smartest::SimpleStub")
|
|
2386
2464
|
|
|
2387
2465
|
gemfile_contents = File.read(File.join(dir, "Gemfile"))
|
|
2466
|
+
expect(gemfile_contents).to include('gem "smartest"')
|
|
2467
|
+
expect(gemfile_contents.scan(/^\s*gem ["']smartest["']/).length).to eq(1)
|
|
2388
2468
|
expect(gemfile_contents).to include('gem "playwright-ruby-client", group: :test')
|
|
2389
2469
|
expect(commands).to eq(
|
|
2390
2470
|
[
|
|
@@ -2398,6 +2478,135 @@ test("cli rails init generator creates Rails browser scaffold and installation c
|
|
|
2398
2478
|
end
|
|
2399
2479
|
end
|
|
2400
2480
|
|
|
2481
|
+
test("cli rails init generator forces Rails test environment when the generated fixture is required") do
|
|
2482
|
+
Dir.mktmpdir do |dir|
|
|
2483
|
+
FileUtils.mkdir_p(File.join(dir, "config"))
|
|
2484
|
+
File.write(File.join(dir, "Gemfile"), <<~RUBY)
|
|
2485
|
+
source "https://rubygems.org"
|
|
2486
|
+
|
|
2487
|
+
gem "rails"
|
|
2488
|
+
gem "smartest"
|
|
2489
|
+
RUBY
|
|
2490
|
+
File.write(File.join(dir, "config/environment.rb"), <<~RUBY)
|
|
2491
|
+
raise "RAILS_ENV was not set before loading Rails" unless ENV["RAILS_ENV"] == "test"
|
|
2492
|
+
raise "RACK_ENV was not set before loading Rails" unless ENV["RACK_ENV"] == "test"
|
|
2493
|
+
|
|
2494
|
+
class User
|
|
2495
|
+
end
|
|
2496
|
+
RUBY
|
|
2497
|
+
|
|
2498
|
+
stub_dir = File.join(dir, "stub_load_path")
|
|
2499
|
+
FileUtils.mkdir_p(File.join(stub_dir, "smartest"))
|
|
2500
|
+
File.write(File.join(stub_dir, "smartest/rails.rb"), <<~RUBY)
|
|
2501
|
+
module Smartest
|
|
2502
|
+
class Fixture
|
|
2503
|
+
def self.suite_fixture(*)
|
|
2504
|
+
end
|
|
2505
|
+
|
|
2506
|
+
def self.fixture(*)
|
|
2507
|
+
end
|
|
2508
|
+
end
|
|
2509
|
+
|
|
2510
|
+
module Rails
|
|
2511
|
+
end
|
|
2512
|
+
end
|
|
2513
|
+
RUBY
|
|
2514
|
+
File.write(File.join(stub_dir, "playwright.rb"), "")
|
|
2515
|
+
|
|
2516
|
+
generator = Smartest::InitRailsGenerator.new(
|
|
2517
|
+
root: dir,
|
|
2518
|
+
output: StringIO.new,
|
|
2519
|
+
command_runner: ->(_command, chdir:) { true }
|
|
2520
|
+
)
|
|
2521
|
+
generator.run
|
|
2522
|
+
|
|
2523
|
+
stdout, stderr, status = Open3.capture3(
|
|
2524
|
+
{
|
|
2525
|
+
"RUBYLIB" => stub_dir,
|
|
2526
|
+
"RAILS_ENV" => "development",
|
|
2527
|
+
"RACK_ENV" => "development"
|
|
2528
|
+
},
|
|
2529
|
+
"ruby",
|
|
2530
|
+
"-e",
|
|
2531
|
+
<<~RUBY
|
|
2532
|
+
require #{File.join(dir, "smartest/fixtures/rails_system_fixture").inspect}
|
|
2533
|
+
puts User.name
|
|
2534
|
+
RUBY
|
|
2535
|
+
)
|
|
2536
|
+
|
|
2537
|
+
expect(status.success?).to eq(true)
|
|
2538
|
+
expect(stderr).to eq("")
|
|
2539
|
+
expect(stdout).to eq("User\n")
|
|
2540
|
+
end
|
|
2541
|
+
end
|
|
2542
|
+
|
|
2543
|
+
test("cli rails init generator runs installation commands outside the current Bundler environment") do
|
|
2544
|
+
require "bundler"
|
|
2545
|
+
|
|
2546
|
+
Dir.mktmpdir do |dir|
|
|
2547
|
+
File.write(File.join(dir, "Gemfile"), <<~RUBY)
|
|
2548
|
+
source "https://rubygems.org"
|
|
2549
|
+
|
|
2550
|
+
gem "rails"
|
|
2551
|
+
gem "smartest"
|
|
2552
|
+
RUBY
|
|
2553
|
+
|
|
2554
|
+
command_environments = []
|
|
2555
|
+
output = StringIO.new
|
|
2556
|
+
generator = Smartest::InitRailsGenerator.new(
|
|
2557
|
+
root: dir,
|
|
2558
|
+
output: output,
|
|
2559
|
+
command_runner: ->(_command, chdir:) {
|
|
2560
|
+
command_environments << {
|
|
2561
|
+
bundle_gemfile: ENV["BUNDLE_GEMFILE"],
|
|
2562
|
+
bundle_bin_path: ENV["BUNDLE_BIN_PATH"],
|
|
2563
|
+
rubyopt: ENV["RUBYOPT"]
|
|
2564
|
+
}
|
|
2565
|
+
true
|
|
2566
|
+
}
|
|
2567
|
+
)
|
|
2568
|
+
|
|
2569
|
+
SmartestSelfTest.with_env(
|
|
2570
|
+
"BUNDLE_GEMFILE" => File.join(dir, "Gemfile"),
|
|
2571
|
+
"BUNDLE_BIN_PATH" => "/tmp/smartest-self-test-bundle",
|
|
2572
|
+
"RUBYOPT" => "-rbundler/setup -W0"
|
|
2573
|
+
) do
|
|
2574
|
+
status = generator.run
|
|
2575
|
+
expect(status).to eq(0)
|
|
2576
|
+
end
|
|
2577
|
+
|
|
2578
|
+
expect(command_environments.length).to eq(4)
|
|
2579
|
+
expect(command_environments.all? do |environment|
|
|
2580
|
+
environment[:bundle_gemfile].nil? &&
|
|
2581
|
+
environment[:bundle_bin_path].nil? &&
|
|
2582
|
+
!environment[:rubyopt].to_s.include?("bundler/setup")
|
|
2583
|
+
end).to eq(true)
|
|
2584
|
+
end
|
|
2585
|
+
end
|
|
2586
|
+
|
|
2587
|
+
test("cli rails init generator keeps smartest in Gemfile when adding Playwright") do
|
|
2588
|
+
Dir.mktmpdir do |dir|
|
|
2589
|
+
File.write(File.join(dir, "Gemfile"), <<~RUBY)
|
|
2590
|
+
source "https://rubygems.org"
|
|
2591
|
+
|
|
2592
|
+
gem "rails"
|
|
2593
|
+
RUBY
|
|
2594
|
+
|
|
2595
|
+
generator = Smartest::InitRailsGenerator.new(
|
|
2596
|
+
root: dir,
|
|
2597
|
+
output: StringIO.new,
|
|
2598
|
+
command_runner: ->(_command, chdir:) { true }
|
|
2599
|
+
)
|
|
2600
|
+
|
|
2601
|
+
status = generator.run
|
|
2602
|
+
|
|
2603
|
+
expect(status).to eq(0)
|
|
2604
|
+
gemfile_contents = File.read(File.join(dir, "Gemfile"))
|
|
2605
|
+
expect(gemfile_contents).to include('gem "smartest"')
|
|
2606
|
+
expect(gemfile_contents).to include('gem "playwright-ruby-client", group: :test')
|
|
2607
|
+
end
|
|
2608
|
+
end
|
|
2609
|
+
|
|
2401
2610
|
test("cli rails init generator skips browser install when requested by environment") do
|
|
2402
2611
|
SmartestSelfTest.with_env("SMARTEST_SKIP_BROWSER_DOWNLOAD" => "1") do
|
|
2403
2612
|
Dir.mktmpdir do |dir|
|
data/smartest.gemspec
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: smartest
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.2.alpha1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yusuke Iwaki
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-05-
|
|
11
|
+
date: 2026-05-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rake
|
|
@@ -78,6 +78,7 @@ files:
|
|
|
78
78
|
- lib/smartest/test_run.rb
|
|
79
79
|
- lib/smartest/test_run_state.rb
|
|
80
80
|
- lib/smartest/version.rb
|
|
81
|
+
- sig/smartest.rbs
|
|
81
82
|
- smartest.gemspec
|
|
82
83
|
- smartest/simple_stub_test.rb
|
|
83
84
|
- smartest/smartest_test.rb
|
|
@@ -103,9 +104,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
103
104
|
version: '2.7'
|
|
104
105
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
105
106
|
requirements:
|
|
106
|
-
- - "
|
|
107
|
+
- - ">"
|
|
107
108
|
- !ruby/object:Gem::Version
|
|
108
|
-
version:
|
|
109
|
+
version: 1.3.1
|
|
109
110
|
requirements: []
|
|
110
111
|
rubygems_version: 3.4.19
|
|
111
112
|
signing_key:
|