ruby_raider 3.8.0 → 3.10.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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +18 -29
  3. data/.github/workflows/security.yml +68 -0
  4. data/.rubocop.yml +28 -0
  5. data/README.md +22 -4
  6. data/docs/superpowers/plans/2026-10-25-failure-video-replay.md +400 -0
  7. data/docs/superpowers/plans/2026-10-26-parity-cleanup.md +233 -0
  8. data/docs/superpowers/plans/2026-10-28-failure-card.md +295 -0
  9. data/docs/superpowers/specs/2026-10-25-failure-video-replay-design.md +214 -0
  10. data/docs/superpowers/specs/2026-10-28-failure-card-design.md +210 -0
  11. data/lib/commands/scaffolding_commands.rb +3 -3
  12. data/lib/commands/utility_commands.rb +36 -6
  13. data/lib/generators/cucumber/templates/cucumber.tt +1 -1
  14. data/lib/generators/cucumber/templates/partials/appium_env.tt +6 -0
  15. data/lib/generators/cucumber/templates/partials/selenium_env.tt +6 -0
  16. data/lib/generators/cucumber/templates/partials/watir_env.tt +6 -0
  17. data/lib/generators/helper_generator.rb +5 -1
  18. data/lib/generators/infrastructure/azure_generator.rb +1 -0
  19. data/lib/generators/infrastructure/github_generator.rb +1 -0
  20. data/lib/generators/infrastructure/templates/azure_pipelines.tt +26 -2
  21. data/lib/generators/infrastructure/templates/github.tt +31 -1
  22. data/lib/generators/infrastructure/templates/github_appium.tt +50 -1
  23. data/lib/generators/invoke_generators.rb +20 -2
  24. data/lib/generators/rspec/rspec_generator.rb +0 -1
  25. data/lib/generators/templates/common/gemfile.tt +1 -1
  26. data/lib/generators/templates/common/git_ignore.tt +3 -0
  27. data/lib/generators/templates/common/partials/mobile_config.tt +5 -0
  28. data/lib/generators/templates/common/partials/web_config.tt +6 -1
  29. data/lib/generators/templates/common/read_me.tt +80 -2
  30. data/lib/generators/templates/helpers/browser_helper.tt +5 -1
  31. data/lib/generators/templates/helpers/driver_helper.tt +1 -0
  32. data/lib/generators/templates/helpers/partials/selenium_driver.tt +4 -1
  33. data/lib/generators/templates/helpers/spec_helper.tt +8 -0
  34. data/lib/generators/templates/helpers/video_helper.tt +338 -171
  35. data/lib/ruby_raider/ffmpeg.rb +280 -0
  36. data/lib/ruby_raider.rb +2 -3
  37. data/lib/scaffolding/project_detector.rb +1 -3
  38. data/lib/scaffolding/scaffolding.rb +0 -1
  39. data/lib/utilities/utilities.rb +15 -2
  40. data/lib/version +1 -1
  41. data/ruby_raider.gemspec +3 -1
  42. data/sig/commands/utility_commands.rbs +4 -1
  43. data/sig/generators/invoke_generators.rbs +2 -3
  44. data/sig/ruby_raider/ffmpeg.rbs +23 -0
  45. data/sig/utilities/utilities.rbs +1 -0
  46. data/spec/commands/raider_commands_spec.rb +56 -1
  47. data/spec/generators/fixtures/video_helper_stubs/selenium-webdriver.rb +28 -0
  48. data/spec/generators/video_helper_spec.rb +608 -0
  49. data/spec/integration/commands/browser_update_after_creation_spec.rb +7 -6
  50. data/spec/integration/commands/utility_commands_spec.rb +2 -2
  51. data/spec/integration/content/azure_content_spec.rb +48 -3
  52. data/spec/integration/content/ci_content_spec.rb +115 -5
  53. data/spec/integration/content/common_content_spec.rb +8 -0
  54. data/spec/integration/content/config_content_spec.rb +14 -0
  55. data/spec/integration/content/cucumber_reporter_content_spec.rb +22 -1
  56. data/spec/integration/content/gemfile_content_spec.rb +2 -3
  57. data/spec/integration/content/helper_content_spec.rb +146 -0
  58. data/spec/integration/content/page_content_spec.rb +0 -1
  59. data/spec/integration/content/readme_content_spec.rb +65 -0
  60. data/spec/integration/content/rspec_reporter_content_spec.rb +2 -2
  61. data/spec/integration/content/test_content_spec.rb +2 -3
  62. data/spec/integration/end_to_end_features_spec.rb +0 -2
  63. data/spec/integration/end_to_end_spec.rb +252 -26
  64. data/spec/integration/generators/azure_generator_spec.rb +7 -6
  65. data/spec/integration/generators/common_generator_spec.rb +1 -1
  66. data/spec/integration/generators/invoke_generators_spec.rb +52 -0
  67. data/spec/integration/scaffolding_e2e_spec.rb +13 -24
  68. data/spec/scaffolding/scaffold_project_detector_spec.rb +0 -1
  69. data/spec/scaffolding/scaffolding_features_spec.rb +0 -1
  70. data/spec/system/selenium_spec.rb +0 -1
  71. data/spec/system/watir_spec.rb +0 -1
  72. data/spec/utilities/ffmpeg_spec.rb +424 -0
  73. data/spec/utilities/utilities_spec.rb +19 -2
  74. data/spec/utilities/video_command_spec.rb +120 -0
  75. metadata +49 -11
  76. data/lib/commands/adopt_commands.rb +0 -42
  77. data/lib/commands/loaded_commands.rb +0 -9
  78. data/lib/commands/plugin_commands.rb +0 -32
  79. data/sig/commands/adopt_commands.rbs +0 -8
  80. data/sig/commands/loaded_commands.rbs +0 -5
  81. data/sig/commands/plugin_commands.rbs +0 -9
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tmpdir'
4
+ require 'fileutils'
5
+ require 'yaml'
6
+ require 'stringio'
7
+ require_relative '../../lib/commands/utility_commands'
8
+
9
+ # rubocop:disable RSpec/FilePath
10
+ RSpec.describe UtilityCommands do
11
+ let(:cache) { Dir.mktmpdir('raider-video-cache') }
12
+ let(:project) { Dir.mktmpdir('raider-video-project') }
13
+ let(:config_path) { File.join(project, 'config', 'config.yml') }
14
+
15
+ around do |example|
16
+ saved = ENV.to_h.slice('RAIDER_CACHE_DIR', 'RAIDER_FFMPEG_PATH')
17
+ ENV['RAIDER_CACHE_DIR'] = cache
18
+ ENV.delete('RAIDER_FFMPEG_PATH')
19
+ FileUtils.mkdir_p(File.join(project, 'config'))
20
+ File.write(config_path, "browser: chrome\ntimeout: 10\n")
21
+ Dir.chdir(project) { example.run }
22
+ ensure
23
+ saved.each { |k, v| ENV[k] = v }
24
+ ENV.delete('RAIDER_CACHE_DIR') unless saved.key?('RAIDER_CACHE_DIR')
25
+ FileUtils.rm_rf([cache, project])
26
+ end
27
+
28
+ def run_cli(*args)
29
+ out = StringIO.new
30
+ err = StringIO.new
31
+ status = 0
32
+ $stdout = out
33
+ $stderr = err
34
+ begin
35
+ described_class.start(args)
36
+ rescue SystemExit => e
37
+ status = e.status
38
+ ensure
39
+ $stdout = STDOUT
40
+ $stderr = STDERR
41
+ end
42
+ [out.string, err.string, status]
43
+ end
44
+
45
+ describe 'video install' do
46
+ it 'exits 1 and explains when the build is not published yet' do
47
+ out, err, status = run_cli('video', 'install')
48
+ expect(status).to eq(1)
49
+ expect(err).to include('[video]', 'ffmpeg build not published yet')
50
+ expect(out).to eq('')
51
+ end
52
+
53
+ it 'prints the path and exits 0 when ensure! succeeds' do
54
+ require 'ruby_raider/ffmpeg'
55
+ allow(RubyRaider::Ffmpeg).to receive(:ensure!).and_return('/tmp/ffmpeg')
56
+ out, _err, status = run_cli('video', 'install')
57
+ expect(status).to eq(0)
58
+ expect(out).to include('/tmp/ffmpeg')
59
+ end
60
+ end
61
+
62
+ describe 'video status' do
63
+ it 'reports not installed with an empty cache' do
64
+ out, _err, status = run_cli('video', 'status')
65
+ expect(status).to eq(0)
66
+ expect(out.strip).to eq('ffmpeg 7.1: not installed')
67
+ end
68
+
69
+ it 'labels a RAIDER_FFMPEG_PATH binary by its source, not the manifest version' do
70
+ script = File.join(cache, 'fake-ffmpeg')
71
+ File.write(script, "#!/bin/sh\n")
72
+ File.chmod(0o755, script)
73
+ ENV['RAIDER_FFMPEG_PATH'] = script
74
+ out, = run_cli('video', 'status')
75
+ expect(out.strip).to eq("ffmpeg (RAIDER_FFMPEG_PATH): #{script}")
76
+ end
77
+
78
+ it 'prints the cached binary with the manifest version without downloading' do
79
+ require 'ruby_raider/ffmpeg'
80
+ allow(RubyRaider::Ffmpeg).to receive(:resolve).and_return('/cache/ffmpeg/7.1/ffmpeg')
81
+ out, = run_cli('video', 'status')
82
+ expect(out.strip).to eq('ffmpeg 7.1: /cache/ffmpeg/7.1/ffmpeg')
83
+ end
84
+ end
85
+
86
+ describe 'video on/off' do
87
+ it 'round-trips video.enabled, keeping other keys' do
88
+ run_cli('video', 'off')
89
+ config = YAML.load_file(config_path)
90
+ expect(config['video']).to eq('enabled' => false)
91
+ expect(config).to include('browser' => 'chrome', 'timeout' => 10)
92
+
93
+ run_cli('video', 'on')
94
+ expect(YAML.load_file(config_path)['video']).to eq('enabled' => true)
95
+ end
96
+
97
+ it 'preserves other keys under video' do
98
+ File.write(config_path, "video:\n enabled: true\n fps: 5\n")
99
+ run_cli('video', 'off')
100
+ expect(YAML.load_file(config_path)['video']).to eq('enabled' => false, 'fps' => 5)
101
+ end
102
+ end
103
+
104
+ describe 'video with an unknown subcommand' do
105
+ it 'exits 1 with usage' do
106
+ _out, err, status = run_cli('video', 'bogus')
107
+ expect(status).to eq(1)
108
+ expect(err).to include('install|status|on|off')
109
+ end
110
+ end
111
+
112
+ describe 'help timeout' do
113
+ it 'does not list the stray config options' do
114
+ out, = run_cli('help', 'timeout')
115
+ expect(out).not_to include('--path')
116
+ expect(out).not_to include('--delete')
117
+ end
118
+ end
119
+ end
120
+ # rubocop:enable RSpec/FilePath
metadata CHANGED
@@ -1,14 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_raider
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.8.0
4
+ version: 3.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Agustin Pequeno
8
+ autorequire:
8
9
  bindir: bin
9
10
  cert_chain: []
10
- date: 2026-10-24 00:00:00.000000000 Z
11
+ date: 2026-10-30 00:00:00.000000000 Z
11
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler-audit
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.9'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.9'
12
27
  - !ruby/object:Gem::Dependency
13
28
  name: rake
14
29
  requirement: !ruby/object:Gem::Requirement
@@ -29,14 +44,14 @@ dependencies:
29
44
  requirements:
30
45
  - - "~>"
31
46
  - !ruby/object:Gem::Version
32
- version: 6.1.0
47
+ version: '6.5'
33
48
  type: :development
34
49
  prerelease: false
35
50
  version_requirements: !ruby/object:Gem::Requirement
36
51
  requirements:
37
52
  - - "~>"
38
53
  - !ruby/object:Gem::Version
39
- version: 6.1.0
54
+ version: '6.5'
40
55
  - !ruby/object:Gem::Dependency
41
56
  name: rspec
42
57
  requirement: !ruby/object:Gem::Requirement
@@ -93,6 +108,20 @@ dependencies:
93
108
  - - "~>"
94
109
  - !ruby/object:Gem::Version
95
110
  version: 2.9.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: ruby_audit
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '3.1'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '3.1'
96
125
  - !ruby/object:Gem::Dependency
97
126
  name: steep
98
127
  requirement: !ruby/object:Gem::Requirement
@@ -151,6 +180,7 @@ files:
151
180
  - ".github/workflows/reek.yml"
152
181
  - ".github/workflows/release.yml"
153
182
  - ".github/workflows/rubocop.yml"
183
+ - ".github/workflows/security.yml"
154
184
  - ".github/workflows/steep.yml"
155
185
  - ".github/workflows/system_tests.yml"
156
186
  - ".gitignore"
@@ -169,9 +199,11 @@ files:
169
199
  - assets/ruby_raider_logo.svg
170
200
  - bin/raider
171
201
  - bin/release
172
- - lib/commands/adopt_commands.rb
173
- - lib/commands/loaded_commands.rb
174
- - lib/commands/plugin_commands.rb
202
+ - docs/superpowers/plans/2026-10-25-failure-video-replay.md
203
+ - docs/superpowers/plans/2026-10-26-parity-cleanup.md
204
+ - docs/superpowers/plans/2026-10-28-failure-card.md
205
+ - docs/superpowers/specs/2026-10-25-failure-video-replay-design.md
206
+ - docs/superpowers/specs/2026-10-28-failure-card-design.md
175
207
  - lib/commands/scaffolding_commands.rb
176
208
  - lib/commands/utility_commands.rb
177
209
  - lib/generators/automation/automation_generator.rb
@@ -246,6 +278,7 @@ files:
246
278
  - lib/generators/templates/helpers/spec_helper.tt
247
279
  - lib/generators/templates/helpers/video_helper.tt
248
280
  - lib/ruby_raider.rb
281
+ - lib/ruby_raider/ffmpeg.rb
249
282
  - lib/scaffolding/name_normalizer.rb
250
283
  - lib/scaffolding/project_detector.rb
251
284
  - lib/scaffolding/scaffolding.rb
@@ -262,9 +295,6 @@ files:
262
295
  - lib/version
263
296
  - plugins.yml
264
297
  - ruby_raider.gemspec
265
- - sig/commands/adopt_commands.rbs
266
- - sig/commands/loaded_commands.rbs
267
- - sig/commands/plugin_commands.rbs
268
298
  - sig/commands/scaffolding_commands.rbs
269
299
  - sig/commands/utility_commands.rbs
270
300
  - sig/generators/automation/automation_generator.rbs
@@ -282,6 +312,7 @@ files:
282
312
  - sig/generators/template_renderer/partial_resolver.rbs
283
313
  - sig/generators/template_renderer/template_error.rbs
284
314
  - sig/ruby_raider.rbs
315
+ - sig/ruby_raider/ffmpeg.rbs
285
316
  - sig/scaffolding/name_normalizer.rbs
286
317
  - sig/scaffolding/project_detector.rbs
287
318
  - sig/scaffolding/scaffolding.rbs
@@ -295,7 +326,9 @@ files:
295
326
  - spec/commands/scaffolding_commands_spec.rb
296
327
  - spec/generators/fixtures/templates/test.tt
297
328
  - spec/generators/fixtures/templates/test_partial.tt
329
+ - spec/generators/fixtures/video_helper_stubs/selenium-webdriver.rb
298
330
  - spec/generators/template_renderer_spec.rb
331
+ - spec/generators/video_helper_spec.rb
299
332
  - spec/integration/commands/browser_update_after_creation_spec.rb
300
333
  - spec/integration/commands/scaffolding_commands_spec.rb
301
334
  - spec/integration/commands/utility_commands_spec.rb
@@ -322,6 +355,7 @@ files:
322
355
  - spec/integration/generators/cucumber_generator_spec.rb
323
356
  - spec/integration/generators/github_generator_spec.rb
324
357
  - spec/integration/generators/helpers_generator_spec.rb
358
+ - spec/integration/generators/invoke_generators_spec.rb
325
359
  - spec/integration/generators/rspec_generator_spec.rb
326
360
  - spec/integration/scaffolding_e2e_spec.rb
327
361
  - spec/integration/settings_helper.rb
@@ -334,12 +368,15 @@ files:
334
368
  - spec/system/support/system_test_helper.rb
335
369
  - spec/system/watir_spec.rb
336
370
  - spec/utilities/desktop_downloader_spec.rb
371
+ - spec/utilities/ffmpeg_spec.rb
337
372
  - spec/utilities/headless_config_spec.rb
338
373
  - spec/utilities/utilities_spec.rb
374
+ - spec/utilities/video_command_spec.rb
339
375
  homepage: https://github.com/RubyRaider/ruby_raider
340
376
  licenses:
341
377
  - MIT
342
378
  metadata: {}
379
+ post_install_message:
343
380
  rdoc_options: []
344
381
  require_paths:
345
382
  - lib
@@ -354,7 +391,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
354
391
  - !ruby/object:Gem::Version
355
392
  version: '0'
356
393
  requirements: []
357
- rubygems_version: 3.6.2
394
+ rubygems_version: 3.5.22
395
+ signing_key:
358
396
  specification_version: 4
359
397
  summary: A gem to make setup and start of UI automation projects easier
360
398
  test_files: []
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'thor'
4
- require_relative '../adopter/adopt_menu'
5
-
6
- class AdoptCommands < Thor
7
- desc 'project [SOURCE_PATH]', 'Adopts an existing test project into Ruby Raider conventions'
8
- option :parameters,
9
- type: :hash, required: false,
10
- desc: 'Parameters to bypass the menu (output_path, target_automation, target_framework, ci_platform)',
11
- aliases: 'p'
12
-
13
- def project(source_path)
14
- params = options[:parameters]
15
- if params
16
- parsed = params.transform_keys(&:to_sym)
17
- parsed[:source_path] = source_path
18
- result = Adopter::AdoptMenu.adopt(parsed)
19
- print_programmatic_results(result)
20
- else
21
- Adopter::AdoptMenu.new.run
22
- end
23
- rescue Adopter::MobileProjectError => e
24
- puts "Error: #{e.message}"
25
- exit 1
26
- rescue ArgumentError => e
27
- puts "Invalid parameters: #{e.message}"
28
- exit 1
29
- end
30
-
31
- private
32
-
33
- def print_programmatic_results(result)
34
- plan = result[:plan]
35
- results = result[:results]
36
- puts "Adoption complete: #{results[:pages]} pages, #{results[:tests]} tests, " \
37
- "#{results[:features]} features, #{results[:steps]} steps"
38
- puts "Warnings: #{plan.warnings.join('; ')}" unless plan.warnings.empty?
39
- puts "Errors: #{results[:errors].join('; ')}" unless results[:errors].empty?
40
- puts "Output: #{plan.output_path}"
41
- end
42
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'thor'
4
- require_relative '../plugin/plugin'
5
-
6
- module RubyRaider
7
- class LoadedCommands < Thor
8
- end
9
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'thor'
4
- require_relative '../plugin/plugin'
5
-
6
- module RubyRaider
7
- class PluginCommands < Thor
8
- desc 'add [NAME]', 'Adds a plugin to your project'
9
-
10
- def add(plugin_name)
11
- Plugin.add_plugin(plugin_name)
12
- end
13
-
14
- desc 'delete [NAME]', 'Deletes a plugin from your project'
15
-
16
- def delete(plugin_name)
17
- Plugin.delete_plugin(plugin_name)
18
- end
19
-
20
- desc 'local', 'Lists all the plugin in your project'
21
-
22
- def local
23
- pp Plugin.installed_plugins
24
- end
25
-
26
- desc 'list', 'Lists all the available plugin'
27
-
28
- def list
29
- pp Plugin.plugins
30
- end
31
- end
32
- end
@@ -1,8 +0,0 @@
1
- # Type definitions for AdoptCommands
2
- class AdoptCommands < Thor
3
- def project: (String source_path) -> void
4
-
5
- private
6
-
7
- def print_programmatic_results: (Hash[Symbol, untyped] result) -> void
8
- end
@@ -1,5 +0,0 @@
1
- # Type definitions for LoadedCommands
2
- module RubyRaider
3
- class LoadedCommands < Thor
4
- end
5
- end
@@ -1,9 +0,0 @@
1
- # Type definitions for PluginCommands
2
- module RubyRaider
3
- class PluginCommands < Thor
4
- def add: (String plugin_name) -> void
5
- def delete: (String plugin_name) -> void
6
- def local: () -> void
7
- def list: () -> void
8
- end
9
- end