ruby_raider 1.1.4 → 3.0.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 (278) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/e2e_tests.yml +58 -0
  3. data/.github/workflows/integration.yml +4 -6
  4. data/.github/workflows/reek.yml +6 -5
  5. data/.github/workflows/release.yml +175 -0
  6. data/.github/workflows/rubocop.yml +7 -6
  7. data/.github/workflows/steep.yml +21 -0
  8. data/.github/workflows/system_tests.yml +83 -0
  9. data/.gitignore +1 -1
  10. data/.reek.yml +46 -4
  11. data/.rubocop.yml +24 -0
  12. data/.ruby-version +1 -1
  13. data/README.md +140 -77
  14. data/RELEASE.md +412 -0
  15. data/RELEASE_QUICK_GUIDE.md +77 -0
  16. data/Steepfile +22 -0
  17. data/assets/ruby_raider_logo.svg +51 -0
  18. data/bin/release +186 -0
  19. data/lib/adopter/adopt_menu.rb +146 -0
  20. data/lib/adopter/converters/base_converter.rb +84 -0
  21. data/lib/adopter/converters/identity_converter.rb +53 -0
  22. data/lib/adopter/migration_plan.rb +74 -0
  23. data/lib/adopter/migrator.rb +96 -0
  24. data/lib/adopter/plan_builder.rb +275 -0
  25. data/lib/adopter/project_analyzer.rb +252 -0
  26. data/lib/adopter/project_detector.rb +157 -0
  27. data/lib/commands/adopt_commands.rb +42 -0
  28. data/lib/commands/plugin_commands.rb +0 -2
  29. data/lib/commands/scaffolding_commands.rb +220 -37
  30. data/lib/commands/utility_commands.rb +82 -2
  31. data/lib/generators/automation/automation_generator.rb +0 -7
  32. data/lib/generators/automation/templates/account.tt +9 -5
  33. data/lib/generators/automation/templates/appium_caps.tt +60 -6
  34. data/lib/generators/automation/templates/home.tt +4 -4
  35. data/lib/generators/automation/templates/login.tt +61 -4
  36. data/lib/generators/automation/templates/page.tt +13 -7
  37. data/lib/generators/automation/templates/partials/element.tt +1 -1
  38. data/lib/generators/automation/templates/partials/home_page_selector.tt +4 -4
  39. data/lib/generators/automation/templates/partials/initialize_selector.tt +3 -8
  40. data/lib/generators/automation/templates/partials/pdp_page_selector.tt +4 -4
  41. data/lib/generators/automation/templates/partials/url_methods.tt +0 -1
  42. data/lib/generators/automation/templates/partials/visit_method.tt +11 -1
  43. data/lib/generators/automation/templates/pdp.tt +1 -1
  44. data/lib/generators/common_generator.rb +12 -0
  45. data/lib/generators/cucumber/cucumber_generator.rb +36 -0
  46. data/lib/generators/cucumber/templates/accessibility_feature.tt +5 -0
  47. data/lib/generators/cucumber/templates/accessibility_steps.tt +21 -0
  48. data/lib/generators/cucumber/templates/cucumber.tt +8 -1
  49. data/lib/generators/cucumber/templates/env.tt +6 -4
  50. data/lib/generators/cucumber/templates/feature.tt +0 -4
  51. data/lib/generators/cucumber/templates/partials/appium_env.tt +5 -0
  52. data/lib/generators/cucumber/templates/partials/capybara_env.tt +38 -0
  53. data/lib/generators/cucumber/templates/partials/capybara_world.tt +6 -0
  54. data/lib/generators/cucumber/templates/partials/driver_world.tt +1 -4
  55. data/lib/generators/cucumber/templates/partials/mobile_steps.tt +2 -2
  56. data/lib/generators/cucumber/templates/partials/selenium_env.tt +22 -35
  57. data/lib/generators/cucumber/templates/partials/watir_env.tt +20 -1
  58. data/lib/generators/cucumber/templates/partials/web_steps.tt +10 -15
  59. data/lib/generators/cucumber/templates/performance_feature.tt +5 -0
  60. data/lib/generators/cucumber/templates/performance_steps.tt +17 -0
  61. data/lib/generators/cucumber/templates/steps.tt +2 -2
  62. data/lib/generators/cucumber/templates/visual_feature.tt +5 -0
  63. data/lib/generators/cucumber/templates/visual_steps.tt +19 -0
  64. data/lib/generators/cucumber/templates/world.tt +5 -3
  65. data/lib/generators/generator.rb +50 -7
  66. data/lib/generators/helper_generator.rb +39 -9
  67. data/lib/generators/infrastructure/github_generator.rb +6 -0
  68. data/lib/generators/infrastructure/templates/github.tt +12 -8
  69. data/lib/generators/infrastructure/templates/github_appium.tt +108 -0
  70. data/lib/generators/infrastructure/templates/gitlab.tt +6 -3
  71. data/lib/generators/invoke_generators.rb +43 -9
  72. data/lib/generators/menu_generator.rb +122 -11
  73. data/lib/generators/minitest/minitest_generator.rb +35 -0
  74. data/lib/generators/minitest/templates/accessibility_test.tt +26 -0
  75. data/lib/generators/minitest/templates/performance_test.tt +18 -0
  76. data/lib/generators/minitest/templates/test.tt +64 -0
  77. data/lib/generators/minitest/templates/visual_test.tt +23 -0
  78. data/lib/generators/rspec/rspec_generator.rb +16 -4
  79. data/lib/generators/rspec/templates/accessibility_spec.tt +25 -0
  80. data/lib/generators/rspec/templates/performance_spec.tt +18 -0
  81. data/lib/generators/rspec/templates/spec.tt +13 -41
  82. data/lib/generators/rspec/templates/visual_spec.tt +20 -0
  83. data/lib/generators/template_renderer/partial_cache.rb +126 -0
  84. data/lib/generators/template_renderer/partial_resolver.rb +110 -0
  85. data/lib/generators/template_renderer/template_error.rb +50 -0
  86. data/lib/generators/template_renderer.rb +106 -0
  87. data/lib/generators/templates/common/config.tt +2 -2
  88. data/lib/generators/templates/common/gemfile.tt +36 -9
  89. data/lib/generators/templates/common/git_ignore.tt +6 -1
  90. data/lib/generators/templates/common/partials/mobile_config.tt +5 -1
  91. data/lib/generators/templates/common/partials/web_config.tt +17 -8
  92. data/lib/generators/templates/common/rakefile.tt +36 -0
  93. data/lib/generators/templates/common/read_me.tt +43 -91
  94. data/lib/generators/templates/common/rspec.tt +3 -0
  95. data/lib/generators/templates/common/ruby_version.tt +1 -0
  96. data/lib/generators/templates/helpers/allure_helper.tt +13 -2
  97. data/lib/generators/templates/helpers/browser_helper.tt +13 -2
  98. data/lib/generators/templates/helpers/capybara_helper.tt +32 -0
  99. data/lib/generators/templates/helpers/debug_helper.tt +190 -0
  100. data/lib/generators/templates/helpers/driver_helper.tt +3 -11
  101. data/lib/generators/templates/helpers/partials/allure_imports.tt +3 -1
  102. data/lib/generators/templates/helpers/partials/allure_requirements.tt +3 -1
  103. data/lib/generators/templates/helpers/partials/appium_driver.tt +44 -0
  104. data/lib/generators/templates/helpers/partials/browserstack_config.tt +13 -0
  105. data/lib/generators/templates/helpers/partials/debug_diagnostics.tt +7 -0
  106. data/lib/generators/templates/helpers/partials/debug_start.tt +7 -0
  107. data/lib/generators/templates/helpers/partials/driver_and_options.tt +5 -115
  108. data/lib/generators/templates/helpers/partials/quit_driver.tt +3 -1
  109. data/lib/generators/templates/helpers/partials/screenshot.tt +3 -1
  110. data/lib/generators/templates/helpers/partials/selenium_driver.tt +26 -0
  111. data/lib/generators/templates/helpers/partials/video_start.tt +9 -0
  112. data/lib/generators/templates/helpers/partials/video_stop.tt +4 -0
  113. data/lib/generators/templates/helpers/performance_helper.tt +57 -0
  114. data/lib/generators/templates/helpers/spec_helper.tt +72 -10
  115. data/lib/generators/templates/helpers/test_helper.tt +94 -0
  116. data/lib/generators/templates/helpers/video_helper.tt +270 -0
  117. data/lib/generators/templates/helpers/visual_helper.tt +39 -46
  118. data/lib/llm/client.rb +79 -0
  119. data/lib/llm/config.rb +57 -0
  120. data/lib/llm/prompts.rb +84 -0
  121. data/lib/llm/provider.rb +27 -0
  122. data/lib/llm/providers/anthropic_provider.rb +43 -0
  123. data/lib/llm/providers/ollama_provider.rb +56 -0
  124. data/lib/llm/providers/openai_provider.rb +42 -0
  125. data/lib/llm/response_parser.rb +67 -0
  126. data/lib/plugin/plugin.rb +22 -20
  127. data/lib/plugin/plugin_exposer.rb +16 -38
  128. data/lib/ruby_raider.rb +51 -11
  129. data/lib/scaffolding/crud_generator.rb +94 -0
  130. data/lib/scaffolding/dry_run_presenter.rb +16 -0
  131. data/lib/scaffolding/name_normalizer.rb +63 -0
  132. data/lib/scaffolding/page_introspector.rb +45 -0
  133. data/lib/scaffolding/project_detector.rb +72 -0
  134. data/lib/scaffolding/scaffold_menu.rb +103 -0
  135. data/lib/scaffolding/scaffolding.rb +158 -11
  136. data/lib/scaffolding/templates/component.tt +30 -0
  137. data/lib/scaffolding/templates/feature.tt +4 -4
  138. data/lib/scaffolding/templates/helper.tt +15 -1
  139. data/lib/scaffolding/templates/page_from_url.tt +75 -0
  140. data/lib/scaffolding/templates/page_object.tt +50 -1
  141. data/lib/scaffolding/templates/spec.tt +33 -2
  142. data/lib/scaffolding/templates/spec_from_page.tt +31 -0
  143. data/lib/scaffolding/templates/spec_from_url.tt +46 -0
  144. data/lib/scaffolding/templates/steps.tt +17 -5
  145. data/lib/scaffolding/url_analyzer.rb +179 -0
  146. data/lib/utilities/desktop_downloader.rb +177 -0
  147. data/lib/utilities/logo.rb +83 -0
  148. data/lib/utilities/utilities.rb +53 -20
  149. data/lib/version +1 -1
  150. data/ruby_raider.gemspec +1 -0
  151. data/sig/adopter/adopt_menu.rbs +25 -0
  152. data/sig/adopter/converters/base_converter.rbs +23 -0
  153. data/sig/adopter/converters/identity_converter.rbs +16 -0
  154. data/sig/adopter/migration_plan.rbs +34 -0
  155. data/sig/adopter/migrator.rbs +21 -0
  156. data/sig/adopter/plan_builder.rbs +38 -0
  157. data/sig/adopter/project_analyzer.rbs +39 -0
  158. data/sig/adopter/project_detector.rbs +26 -0
  159. data/sig/commands/adopt_commands.rbs +8 -0
  160. data/sig/commands/loaded_commands.rbs +5 -0
  161. data/sig/commands/plugin_commands.rbs +9 -0
  162. data/sig/commands/scaffolding_commands.rbs +28 -0
  163. data/sig/commands/utility_commands.rbs +21 -0
  164. data/sig/generators/automation/automation_generator.rbs +20 -0
  165. data/sig/generators/common_generator.rbs +12 -0
  166. data/sig/generators/cucumber/cucumber_generator.rbs +16 -0
  167. data/sig/generators/generator.rbs +40 -0
  168. data/sig/generators/helper_generator.rbs +18 -0
  169. data/sig/generators/infrastructure/github_generator.rbs +5 -0
  170. data/sig/generators/infrastructure/gitlab_generator.rbs +4 -0
  171. data/sig/generators/invoke_generators.rbs +10 -0
  172. data/sig/generators/menu_generator.rbs +29 -0
  173. data/sig/generators/minitest/minitest_generator.rbs +8 -0
  174. data/sig/generators/rspec/rspec_generator.rbs +8 -0
  175. data/sig/generators/template_renderer/partial_cache.rbs +20 -0
  176. data/sig/generators/template_renderer/partial_resolver.rbs +20 -0
  177. data/sig/generators/template_renderer/template_error.rbs +19 -0
  178. data/sig/generators/template_renderer.rbs +10 -0
  179. data/sig/llm/client.rbs +15 -0
  180. data/sig/llm/config.rbs +20 -0
  181. data/sig/llm/prompts.rbs +8 -0
  182. data/sig/llm/provider.rbs +12 -0
  183. data/sig/llm/providers/anthropic_provider.rbs +16 -0
  184. data/sig/llm/providers/ollama_provider.rbs +18 -0
  185. data/sig/llm/providers/openai_provider.rbs +16 -0
  186. data/sig/llm/response_parser.rbs +13 -0
  187. data/sig/plugin/plugin.rbs +24 -0
  188. data/sig/plugin/plugin_exposer.rbs +20 -0
  189. data/sig/ruby_raider.rbs +15 -0
  190. data/sig/scaffolding/crud_generator.rbs +16 -0
  191. data/sig/scaffolding/dry_run_presenter.rbs +4 -0
  192. data/sig/scaffolding/name_normalizer.rbs +17 -0
  193. data/sig/scaffolding/page_introspector.rbs +14 -0
  194. data/sig/scaffolding/project_detector.rbs +14 -0
  195. data/sig/scaffolding/scaffold_menu.rbs +18 -0
  196. data/sig/scaffolding/scaffolding.rbs +55 -0
  197. data/sig/scaffolding/url_analyzer.rbs +28 -0
  198. data/sig/utilities/desktop_downloader.rbs +23 -0
  199. data/sig/utilities/logger.rbs +13 -0
  200. data/sig/utilities/logo.rbs +16 -0
  201. data/sig/utilities/utilities.rbs +30 -0
  202. data/sig/vendor/thor.rbs +34 -0
  203. data/sig/vendor/tty_prompt.rbs +15 -0
  204. data/spec/adopter/adopt_menu_spec.rb +176 -0
  205. data/spec/adopter/converters/identity_converter_spec.rb +145 -0
  206. data/spec/adopter/migration_plan_spec.rb +113 -0
  207. data/spec/adopter/migrator_spec.rb +277 -0
  208. data/spec/adopter/plan_builder_spec.rb +298 -0
  209. data/spec/adopter/project_analyzer_spec.rb +337 -0
  210. data/spec/adopter/project_detector_spec.rb +295 -0
  211. data/spec/commands/raider_commands_spec.rb +129 -0
  212. data/spec/generators/fixtures/templates/test.tt +1 -0
  213. data/spec/generators/fixtures/templates/test_partial.tt +1 -0
  214. data/spec/generators/generator_spec.rb +23 -0
  215. data/spec/generators/template_renderer_spec.rb +298 -0
  216. data/spec/integration/commands/scaffolding_commands_spec.rb +2 -2
  217. data/spec/integration/commands/utility_commands_spec.rb +24 -4
  218. data/spec/integration/content/ci_content_spec.rb +119 -0
  219. data/spec/integration/content/common_content_spec.rb +288 -0
  220. data/spec/integration/content/config_content_spec.rb +175 -0
  221. data/spec/integration/content/content_helper.rb +32 -0
  222. data/spec/integration/content/gemfile_content_spec.rb +209 -0
  223. data/spec/integration/content/helper_content_spec.rb +485 -0
  224. data/spec/integration/content/page_content_spec.rb +259 -0
  225. data/spec/integration/content/reporter_content_spec.rb +236 -0
  226. data/spec/integration/content/skip_flags_content_spec.rb +206 -0
  227. data/spec/integration/content/syntax_validation_spec.rb +30 -0
  228. data/spec/integration/content/test_content_spec.rb +266 -0
  229. data/spec/integration/end_to_end_features_spec.rb +690 -0
  230. data/spec/integration/end_to_end_spec.rb +361 -0
  231. data/spec/integration/generators/automation_generator_spec.rb +9 -21
  232. data/spec/integration/generators/axe_addon_spec.rb +150 -0
  233. data/spec/integration/generators/common_generator_spec.rb +48 -49
  234. data/spec/integration/generators/config_features_spec.rb +155 -0
  235. data/spec/integration/generators/cucumber_generator_spec.rb +7 -7
  236. data/spec/integration/generators/debug_helper_spec.rb +68 -0
  237. data/spec/integration/generators/github_generator_spec.rb +8 -8
  238. data/spec/integration/generators/gitlab_generator_spec.rb +8 -8
  239. data/spec/integration/generators/helpers_generator_spec.rb +70 -44
  240. data/spec/integration/generators/lighthouse_addon_spec.rb +132 -0
  241. data/spec/integration/generators/minitest_generator_spec.rb +64 -0
  242. data/spec/integration/generators/reporter_spec.rb +159 -0
  243. data/spec/integration/generators/rspec_generator_spec.rb +7 -7
  244. data/spec/integration/generators/skip_flags_spec.rb +134 -0
  245. data/spec/integration/generators/visual_addon_spec.rb +148 -0
  246. data/spec/integration/settings_helper.rb +1 -4
  247. data/spec/integration/spec_helper.rb +46 -11
  248. data/spec/llm/client_spec.rb +79 -0
  249. data/spec/llm/config_spec.rb +92 -0
  250. data/spec/llm/prompts_spec.rb +49 -0
  251. data/spec/llm/response_parser_spec.rb +92 -0
  252. data/spec/menus/adopter_adopt_menu_spec.rb +97 -0
  253. data/spec/menus/menu_generator_spec.rb +263 -0
  254. data/spec/scaffolding/name_normalizer_spec.rb +113 -0
  255. data/spec/scaffolding/page_introspector_spec.rb +82 -0
  256. data/spec/scaffolding/scaffold_project_detector_spec.rb +104 -0
  257. data/spec/scaffolding/scaffolding_features_spec.rb +311 -0
  258. data/spec/scaffolding/url_analyzer_spec.rb +110 -0
  259. data/spec/system/adopt_matrix_spec.rb +537 -0
  260. data/spec/system/adopt_spec.rb +225 -0
  261. data/spec/system/capybara_spec.rb +42 -0
  262. data/spec/system/selenium_spec.rb +19 -17
  263. data/spec/system/support/system_test_helper.rb +33 -0
  264. data/spec/system/watir_spec.rb +19 -17
  265. data/spec/utilities/desktop_downloader_spec.rb +92 -0
  266. metadata +193 -18
  267. data/.github/workflows/push_gem.yml +0 -37
  268. data/.github/workflows/selenium.yml +0 -22
  269. data/.github/workflows/watir.yml +0 -22
  270. data/lib/generators/automation/templates/partials/android_caps.tt +0 -17
  271. data/lib/generators/automation/templates/partials/cross_platform_caps.tt +0 -25
  272. data/lib/generators/automation/templates/partials/ios_caps.tt +0 -18
  273. data/lib/generators/automation/templates/partials/selenium_account.tt +0 -9
  274. data/lib/generators/automation/templates/partials/selenium_login.tt +0 -34
  275. data/lib/generators/automation/templates/partials/watir_account.tt +0 -7
  276. data/lib/generators/automation/templates/partials/watir_login.tt +0 -32
  277. data/lib/generators/automation/templates/visual_options.tt +0 -16
  278. data/lib/generators/templates/helpers/visual_spec_helper.tt +0 -35
@@ -0,0 +1,361 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'spec_helper'
4
+ require 'timeout'
5
+ require 'open3'
6
+
7
+ # End-to-end integration tests that verify generated projects actually work
8
+ # These tests:
9
+ # 1. Generate a complete project
10
+ # 2. Install dependencies (bundle install)
11
+ # 3. Run the generated tests (rspec/cucumber)
12
+ # 4. Verify tests pass
13
+ #
14
+ # This ensures the template system produces working, executable test frameworks
15
+ describe 'End-to-End Project Generation and Execution' do
16
+ # Helper to run commands in a generated project directory
17
+ def run_in_project(project_name, command, timeout: 300)
18
+ result = {
19
+ success: false,
20
+ stdout: '',
21
+ stderr: '',
22
+ exit_code: nil
23
+ }
24
+
25
+ Dir.chdir(project_name) do
26
+ Bundler.with_unbundled_env do
27
+ Timeout.timeout(timeout) do
28
+ stdout, stderr, status = Open3.capture3(command)
29
+ result[:stdout] = stdout
30
+ result[:stderr] = stderr
31
+ result[:exit_code] = status.exitstatus
32
+ result[:success] = status.success?
33
+ end
34
+ end
35
+ end
36
+
37
+ result
38
+ rescue Timeout::Error
39
+ result[:stderr] = "Command timed out after #{timeout} seconds"
40
+ result[:exit_code] = -1
41
+ result
42
+ end
43
+
44
+ # Helper to install dependencies
45
+ def bundle_install(project_name)
46
+ puts "\n📦 Installing dependencies for #{project_name}..."
47
+ result = run_in_project(project_name, 'bundle install --quiet', timeout: 180)
48
+
49
+ unless result[:success]
50
+ puts '❌ Bundle install failed:'
51
+ puts result[:stderr]
52
+ puts result[:stdout]
53
+ end
54
+
55
+ result[:success]
56
+ end
57
+
58
+ # Helper to run RSpec tests
59
+ def run_rspec(project_name)
60
+ puts "\n🧪 Running RSpec tests in #{project_name}..."
61
+ result = run_in_project(project_name, 'bundle exec rspec spec/ --format documentation', timeout: 120)
62
+
63
+ puts result[:stdout] if result[:stdout].length.positive?
64
+
65
+ unless result[:success]
66
+ puts '❌ RSpec tests failed:'
67
+ puts result[:stderr] if result[:stderr].length.positive?
68
+ end
69
+
70
+ result
71
+ end
72
+
73
+ # Helper to run Cucumber tests
74
+ def run_cucumber(project_name)
75
+ puts "\n🥒 Running Cucumber tests in #{project_name}..."
76
+ result = run_in_project(project_name, 'bundle exec cucumber features/ --format pretty', timeout: 120)
77
+
78
+ puts result[:stdout] if result[:stdout].length.positive?
79
+
80
+ unless result[:success]
81
+ puts '❌ Cucumber tests failed:'
82
+ puts result[:stderr] if result[:stderr].length.positive?
83
+ end
84
+
85
+ result
86
+ end
87
+
88
+ # Helper to run Minitest tests
89
+ def run_minitest(project_name)
90
+ puts "\nRunning Minitest tests in #{project_name}..."
91
+ result = run_in_project(project_name, 'bundle exec ruby -Itest test/test_login_page.rb', timeout: 120)
92
+
93
+ puts result[:stdout] if result[:stdout].length.positive?
94
+
95
+ unless result[:success]
96
+ puts 'Minitest tests failed:'
97
+ puts result[:stderr] if result[:stderr].length.positive?
98
+ end
99
+
100
+ result
101
+ end
102
+
103
+ # Shared example for RSpec-based projects
104
+ shared_examples 'executable rspec project' do |project_name|
105
+ let(:project) { project_name }
106
+
107
+ it 'installs dependencies successfully' do
108
+ expect(bundle_install(project)).to be true
109
+ end
110
+
111
+ it 'runs generated RSpec tests successfully', :slow do
112
+ skip 'Bundle install failed' unless bundle_install(project)
113
+
114
+ result = run_rspec(project)
115
+
116
+ expect(result[:success]).to be(true),
117
+ "RSpec tests failed with exit code #{result[:exit_code]}.\n" \
118
+ "STDOUT: #{result[:stdout]}\n" \
119
+ "STDERR: #{result[:stderr]}"
120
+ end
121
+ end
122
+
123
+ # Shared example for Cucumber-based projects
124
+ shared_examples 'executable cucumber project' do |project_name|
125
+ let(:project) { project_name }
126
+
127
+ it 'installs dependencies successfully' do
128
+ expect(bundle_install(project)).to be true
129
+ end
130
+
131
+ it 'runs generated Cucumber tests successfully', :slow do
132
+ skip 'Bundle install failed' unless bundle_install(project)
133
+
134
+ result = run_cucumber(project)
135
+
136
+ expect(result[:success]).to be(true),
137
+ "Cucumber tests failed with exit code #{result[:exit_code]}.\n" \
138
+ "STDOUT: #{result[:stdout]}\n" \
139
+ "STDERR: #{result[:stderr]}"
140
+ end
141
+ end
142
+
143
+ # Shared example for Minitest-based projects
144
+ shared_examples 'executable minitest project' do |project_name|
145
+ let(:project) { project_name }
146
+
147
+ it 'installs dependencies successfully' do
148
+ expect(bundle_install(project)).to be true
149
+ end
150
+
151
+ it 'runs generated Minitest tests successfully', :slow do
152
+ skip 'Bundle install failed' unless bundle_install(project)
153
+
154
+ result = run_minitest(project)
155
+
156
+ expect(result[:success]).to be(true),
157
+ "Minitest tests failed with exit code #{result[:exit_code]}.\n" \
158
+ "STDOUT: #{result[:stdout]}\n" \
159
+ "STDERR: #{result[:stderr]}"
160
+ end
161
+ end
162
+
163
+ # Test Web Frameworks (these can run without external services)
164
+ context 'Web Automation Frameworks' do
165
+ describe 'Selenium + RSpec' do
166
+ include_examples 'executable rspec project', 'rspec_selenium'
167
+ end
168
+
169
+ describe 'Watir + RSpec' do
170
+ include_examples 'executable rspec project', 'rspec_watir'
171
+ end
172
+
173
+ describe 'Capybara + RSpec' do
174
+ include_examples 'executable rspec project', 'rspec_capybara'
175
+ end
176
+
177
+ describe 'Selenium + Cucumber' do
178
+ include_examples 'executable cucumber project', 'cucumber_selenium'
179
+ end
180
+
181
+ describe 'Watir + Cucumber' do
182
+ include_examples 'executable cucumber project', 'cucumber_watir'
183
+ end
184
+
185
+ describe 'Capybara + Cucumber' do
186
+ include_examples 'executable cucumber project', 'cucumber_capybara'
187
+ end
188
+
189
+ describe 'Selenium + Minitest' do
190
+ include_examples 'executable minitest project', 'minitest_selenium'
191
+ end
192
+
193
+ describe 'Watir + Minitest' do
194
+ include_examples 'executable minitest project', 'minitest_watir'
195
+ end
196
+
197
+ describe 'Capybara + Minitest' do
198
+ include_examples 'executable minitest project', 'minitest_capybara'
199
+ end
200
+ end
201
+
202
+ # Mobile and Visual frameworks require external services, so we only verify structure
203
+ context 'Mobile Automation Frameworks (structure validation only)' do
204
+ describe 'iOS + RSpec' do
205
+ it 'generates valid project structure' do
206
+ expect(File).to exist('rspec_ios/helpers/spec_helper.rb')
207
+ expect(File).to exist('rspec_ios/Gemfile')
208
+ expect(File).to exist('rspec_ios/spec')
209
+ end
210
+
211
+ it 'has valid Ruby syntax in generated files' do
212
+ result = run_in_project('rspec_ios', 'ruby -c helpers/spec_helper.rb')
213
+ expect(result[:success]).to be true
214
+ end
215
+ end
216
+
217
+ describe 'iOS + Cucumber' do
218
+ it 'generates valid project structure' do
219
+ expect(File).to exist('cucumber_ios/features/support/env.rb')
220
+ expect(File).to exist('cucumber_ios/Gemfile')
221
+ expect(File).to exist('cucumber_ios/features')
222
+ end
223
+
224
+ it 'has valid Ruby syntax in generated files' do
225
+ result = run_in_project('cucumber_ios', 'ruby -c features/support/env.rb')
226
+ expect(result[:success]).to be true
227
+ end
228
+ end
229
+
230
+ describe 'Android + RSpec' do
231
+ it 'generates valid project structure' do
232
+ expect(File).to exist('rspec_android/helpers/spec_helper.rb')
233
+ expect(File).to exist('rspec_android/Gemfile')
234
+ expect(File).to exist('rspec_android/spec')
235
+ end
236
+
237
+ it 'has valid Ruby syntax in generated files' do
238
+ result = run_in_project('rspec_android', 'ruby -c helpers/spec_helper.rb')
239
+ expect(result[:success]).to be true
240
+ end
241
+ end
242
+
243
+ describe 'Android + Cucumber' do
244
+ it 'generates valid project structure' do
245
+ expect(File).to exist('cucumber_android/features/support/env.rb')
246
+ expect(File).to exist('cucumber_android/Gemfile')
247
+ expect(File).to exist('cucumber_android/features')
248
+ end
249
+
250
+ it 'has valid Ruby syntax in generated files' do
251
+ result = run_in_project('cucumber_android', 'ruby -c features/support/env.rb')
252
+ expect(result[:success]).to be true
253
+ end
254
+ end
255
+
256
+ describe 'Cross-Platform + RSpec' do
257
+ it 'generates valid project structure' do
258
+ expect(File).to exist('rspec_cross_platform/helpers/appium_helper.rb')
259
+ expect(File).to exist('rspec_cross_platform/Gemfile')
260
+ expect(File).to exist('rspec_cross_platform/spec')
261
+ end
262
+
263
+ it 'has valid Ruby syntax in generated files' do
264
+ result = run_in_project('rspec_cross_platform', 'ruby -c helpers/spec_helper.rb')
265
+ expect(result[:success]).to be true
266
+ end
267
+ end
268
+
269
+ describe 'Cross-Platform + Cucumber' do
270
+ it 'generates valid project structure' do
271
+ expect(File).to exist('cucumber_cross_platform/helpers/appium_helper.rb')
272
+ expect(File).to exist('cucumber_cross_platform/Gemfile')
273
+ expect(File).to exist('cucumber_cross_platform/features')
274
+ end
275
+
276
+ it 'has valid Ruby syntax in generated files' do
277
+ result = run_in_project('cucumber_cross_platform', 'ruby -c features/support/env.rb')
278
+ expect(result[:success]).to be true
279
+ end
280
+ end
281
+ end
282
+
283
+ context 'Minitest Mobile Frameworks (structure validation only)' do
284
+ describe 'Android + Minitest' do
285
+ it 'generates valid project structure' do
286
+ expect(File).to exist('minitest_android/helpers/test_helper.rb')
287
+ expect(File).to exist('minitest_android/Gemfile')
288
+ expect(File).to exist('minitest_android/test')
289
+ end
290
+
291
+ it 'has valid Ruby syntax in generated files' do
292
+ result = run_in_project('minitest_android', 'ruby -c helpers/test_helper.rb')
293
+ expect(result[:success]).to be true
294
+ end
295
+ end
296
+
297
+ describe 'iOS + Minitest' do
298
+ it 'generates valid project structure' do
299
+ expect(File).to exist('minitest_ios/helpers/test_helper.rb')
300
+ expect(File).to exist('minitest_ios/Gemfile')
301
+ expect(File).to exist('minitest_ios/test')
302
+ end
303
+
304
+ it 'has valid Ruby syntax in generated files' do
305
+ result = run_in_project('minitest_ios', 'ruby -c helpers/test_helper.rb')
306
+ expect(result[:success]).to be true
307
+ end
308
+ end
309
+
310
+ describe 'Cross-Platform + Minitest' do
311
+ it 'generates valid project structure' do
312
+ expect(File).to exist('minitest_cross_platform/helpers/test_helper.rb')
313
+ expect(File).to exist('minitest_cross_platform/helpers/appium_helper.rb')
314
+ expect(File).to exist('minitest_cross_platform/Gemfile')
315
+ expect(File).to exist('minitest_cross_platform/test')
316
+ end
317
+
318
+ it 'has valid Ruby syntax in generated files' do
319
+ result = run_in_project('minitest_cross_platform', 'ruby -c helpers/test_helper.rb')
320
+ expect(result[:success]).to be true
321
+ end
322
+ end
323
+ end
324
+
325
+ # Verify template system performance (caching working)
326
+ context 'Template System Performance' do
327
+ it 'benefits from template caching on second generation' do
328
+ require_relative '../../lib/generators/generator'
329
+
330
+ # Clear cache
331
+ Generator.clear_template_cache
332
+
333
+ # First generation (cache miss)
334
+ start_time = Time.now
335
+ settings1 = create_settings(framework: 'rspec', automation: 'selenium')
336
+ settings1[:name] = 'test_cache_1'
337
+ generate_framework(settings1)
338
+ first_duration = Time.now - start_time
339
+
340
+ # Second generation (cache hit)
341
+ start_time = Time.now
342
+ settings2 = create_settings(framework: 'rspec', automation: 'selenium')
343
+ settings2[:name] = 'test_cache_2'
344
+ generate_framework(settings2)
345
+ second_duration = Time.now - start_time
346
+
347
+ # Second generation should be faster (or similar if I/O dominates)
348
+ # At minimum, cache should not slow things down
349
+ expect(second_duration).to be <= (first_duration * 1.2)
350
+
351
+ # Cleanup
352
+ FileUtils.rm_rf('test_cache_1')
353
+ FileUtils.rm_rf('test_cache_2')
354
+
355
+ # Verify cache has entries
356
+ stats = Generator.template_cache_stats
357
+ expect(stats[:size]).to be > 0
358
+ puts "\n📊 Template cache: #{stats[:size]} entries, ~#{stats[:memory_estimate] / 1024}KB"
359
+ end
360
+ end
361
+ end
@@ -36,51 +36,39 @@ describe AutomationGenerator do
36
36
  end
37
37
  end
38
38
 
39
- shared_examples 'creates web visual framework' do |name|
40
- it 'creates a login page file' do
41
- expect(File).to exist("#{name}/page_objects/pages/login.rb")
42
- end
43
-
44
- it 'creates an abstract page file' do
45
- expect(File).to exist("#{name}/page_objects/abstract/page.rb")
46
- end
47
- end
48
-
49
39
  context 'with rspec and selenium' do
50
- include_examples 'creates web automation framework', "#{FRAMEWORKS.last}_#{AUTOMATION_TYPES[2]}"
51
- include_examples 'creates web visual framework', "#{FRAMEWORKS.last}_#{AUTOMATION_TYPES.last}"
40
+ include_examples 'creates web automation framework', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::SELENIUM}"
52
41
  end
53
42
 
54
43
  context 'with rspec and watir' do
55
- include_examples 'creates web automation framework', "#{FRAMEWORKS.last}_#{AUTOMATION_TYPES[3]}"
44
+ include_examples 'creates web automation framework', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::WATIR}"
56
45
  end
57
46
 
58
47
  context 'with cucumber and selenium' do
59
- include_examples 'creates web automation framework', "#{FRAMEWORKS.first}_#{AUTOMATION_TYPES[2]}"
60
- include_examples 'creates web visual framework', "#{FRAMEWORKS.first}_#{AUTOMATION_TYPES.last}"
48
+ include_examples 'creates web automation framework', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::SELENIUM}"
61
49
  end
62
50
 
63
51
  context 'with cucumber and watir' do
64
- include_examples 'creates web automation framework', "#{FRAMEWORKS.first}_#{AUTOMATION_TYPES[3]}"
52
+ include_examples 'creates web automation framework', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::WATIR}"
65
53
  end
66
54
 
67
55
  context 'with rspec and appium android' do
68
- include_examples 'creates mobile automation framework', "#{FRAMEWORKS.last}_#{AUTOMATION_TYPES.first}"
56
+ include_examples 'creates mobile automation framework', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::ANDROID}"
69
57
  end
70
58
 
71
59
  context 'with rspec and appium ios' do
72
- include_examples 'creates mobile automation framework', "#{FRAMEWORKS.last}_#{AUTOMATION_TYPES[1]}"
60
+ include_examples 'creates mobile automation framework', "#{FrameworkIndex::RSPEC}_#{AutomationIndex::IOS}"
73
61
  end
74
62
 
75
63
  context 'with cucumber and appium android' do
76
- include_examples 'creates mobile automation framework', "#{FRAMEWORKS.first}_#{AUTOMATION_TYPES.first}"
64
+ include_examples 'creates mobile automation framework', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::ANDROID}"
77
65
  end
78
66
 
79
67
  context 'with cucumber and appium ios' do
80
- include_examples 'creates mobile automation framework', "#{FRAMEWORKS.first}_#{AUTOMATION_TYPES[1]}"
68
+ include_examples 'creates mobile automation framework', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::IOS}"
81
69
  end
82
70
 
83
71
  context 'with cucumber and appium cross platform' do
84
- include_examples 'creates mobile automation framework', "#{FRAMEWORKS.first}_#{AUTOMATION_TYPES[4]}"
72
+ include_examples 'creates mobile automation framework', "#{FrameworkIndex::CUCUMBER}_#{AutomationIndex::CROSS_PLATFORM}"
85
73
  end
86
74
  end
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+ require_relative '../../../lib/generators/invoke_generators'
5
+ require_relative '../settings_helper'
6
+
7
+ describe 'Axe accessibility addon generation' do
8
+ include InvokeGenerators
9
+ include SettingsHelper
10
+
11
+ # rubocop:disable RSpec/BeforeAfterAll, RSpec/InstanceVariable
12
+ before(:all) do
13
+ @axe_projects = []
14
+ %w[rspec cucumber minitest].each do |framework|
15
+ %w[selenium watir capybara].each do |automation|
16
+ name = "axe_#{framework}_#{automation}"
17
+ @axe_projects << name
18
+ InvokeGenerators.generate_framework(
19
+ automation:, framework:, name:, accessibility: true
20
+ )
21
+ end
22
+ end
23
+ end
24
+
25
+ after(:all) do
26
+ @axe_projects.each { |name| FileUtils.rm_rf(name) }
27
+ end
28
+ # rubocop:enable RSpec/BeforeAfterAll, RSpec/InstanceVariable
29
+
30
+ context 'with rspec and selenium' do
31
+ let(:name) { 'axe_rspec_selenium' }
32
+
33
+ it 'creates accessibility_spec.rb' do
34
+ expect(File).to exist("#{name}/spec/accessibility_spec.rb")
35
+ end
36
+
37
+ it 'includes axe gems in Gemfile' do
38
+ gemfile = File.read("#{name}/Gemfile")
39
+ expect(gemfile).to include('axe')
40
+ end
41
+
42
+ it 'accessibility spec has valid Ruby syntax' do
43
+ content = File.read("#{name}/spec/accessibility_spec.rb")
44
+ expect { RubyVM::InstructionSequence.compile(content) }.not_to raise_error
45
+ end
46
+ end
47
+
48
+ context 'with cucumber and selenium' do
49
+ let(:name) { 'axe_cucumber_selenium' }
50
+
51
+ it 'creates accessibility.feature' do
52
+ expect(File).to exist("#{name}/features/accessibility.feature")
53
+ end
54
+
55
+ it 'creates accessibility_steps.rb' do
56
+ expect(File).to exist("#{name}/features/step_definitions/accessibility_steps.rb")
57
+ end
58
+
59
+ it 'includes axe gems in Gemfile' do
60
+ gemfile = File.read("#{name}/Gemfile")
61
+ expect(gemfile).to include('axe')
62
+ end
63
+ end
64
+
65
+ context 'with minitest and selenium' do
66
+ let(:name) { 'axe_minitest_selenium' }
67
+
68
+ it 'creates test_accessibility.rb' do
69
+ expect(File).to exist("#{name}/test/test_accessibility.rb")
70
+ end
71
+
72
+ it 'includes axe gems in Gemfile' do
73
+ gemfile = File.read("#{name}/Gemfile")
74
+ expect(gemfile).to include('axe')
75
+ end
76
+
77
+ it 'accessibility test has valid Ruby syntax' do
78
+ content = File.read("#{name}/test/test_accessibility.rb")
79
+ expect { RubyVM::InstructionSequence.compile(content) }.not_to raise_error
80
+ end
81
+ end
82
+
83
+ context 'with rspec and watir' do
84
+ let(:name) { 'axe_rspec_watir' }
85
+
86
+ it 'creates accessibility_spec.rb' do
87
+ expect(File).to exist("#{name}/spec/accessibility_spec.rb")
88
+ end
89
+ end
90
+
91
+ context 'with rspec and capybara' do
92
+ let(:name) { 'axe_rspec_capybara' }
93
+
94
+ it 'creates accessibility_spec.rb' do
95
+ expect(File).to exist("#{name}/spec/accessibility_spec.rb")
96
+ end
97
+ end
98
+
99
+ context 'with cucumber and watir' do
100
+ let(:name) { 'axe_cucumber_watir' }
101
+
102
+ it 'creates accessibility.feature' do
103
+ expect(File).to exist("#{name}/features/accessibility.feature")
104
+ end
105
+ end
106
+
107
+ context 'with cucumber and capybara' do
108
+ let(:name) { 'axe_cucumber_capybara' }
109
+
110
+ it 'creates accessibility.feature' do
111
+ expect(File).to exist("#{name}/features/accessibility.feature")
112
+ end
113
+ end
114
+
115
+ context 'with minitest and watir' do
116
+ let(:name) { 'axe_minitest_watir' }
117
+
118
+ it 'creates test_accessibility.rb' do
119
+ expect(File).to exist("#{name}/test/test_accessibility.rb")
120
+ end
121
+ end
122
+
123
+ context 'with minitest and capybara' do
124
+ let(:name) { 'axe_minitest_capybara' }
125
+
126
+ it 'creates test_accessibility.rb' do
127
+ expect(File).to exist("#{name}/test/test_accessibility.rb")
128
+ end
129
+ end
130
+
131
+ context 'without accessibility flag' do
132
+ let(:name) { 'no_axe_rspec_selenium' }
133
+
134
+ # rubocop:disable RSpec/BeforeAfterAll
135
+ before(:all) do
136
+ InvokeGenerators.generate_framework(
137
+ automation: 'selenium', framework: 'rspec', name: 'no_axe_rspec_selenium'
138
+ )
139
+ end
140
+
141
+ after(:all) do
142
+ FileUtils.rm_rf('no_axe_rspec_selenium')
143
+ end
144
+ # rubocop:enable RSpec/BeforeAfterAll
145
+
146
+ it 'does not create accessibility_spec.rb' do
147
+ expect(File).not_to exist("#{name}/spec/accessibility_spec.rb")
148
+ end
149
+ end
150
+ end