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.
- checksums.yaml +4 -4
- data/.github/workflows/e2e_tests.yml +58 -0
- data/.github/workflows/integration.yml +4 -6
- data/.github/workflows/reek.yml +6 -5
- data/.github/workflows/release.yml +175 -0
- data/.github/workflows/rubocop.yml +7 -6
- data/.github/workflows/steep.yml +21 -0
- data/.github/workflows/system_tests.yml +83 -0
- data/.gitignore +1 -1
- data/.reek.yml +46 -4
- data/.rubocop.yml +24 -0
- data/.ruby-version +1 -1
- data/README.md +140 -77
- data/RELEASE.md +412 -0
- data/RELEASE_QUICK_GUIDE.md +77 -0
- data/Steepfile +22 -0
- data/assets/ruby_raider_logo.svg +51 -0
- data/bin/release +186 -0
- data/lib/adopter/adopt_menu.rb +146 -0
- data/lib/adopter/converters/base_converter.rb +84 -0
- data/lib/adopter/converters/identity_converter.rb +53 -0
- data/lib/adopter/migration_plan.rb +74 -0
- data/lib/adopter/migrator.rb +96 -0
- data/lib/adopter/plan_builder.rb +275 -0
- data/lib/adopter/project_analyzer.rb +252 -0
- data/lib/adopter/project_detector.rb +157 -0
- data/lib/commands/adopt_commands.rb +42 -0
- data/lib/commands/plugin_commands.rb +0 -2
- data/lib/commands/scaffolding_commands.rb +220 -37
- data/lib/commands/utility_commands.rb +82 -2
- data/lib/generators/automation/automation_generator.rb +0 -7
- data/lib/generators/automation/templates/account.tt +9 -5
- data/lib/generators/automation/templates/appium_caps.tt +60 -6
- data/lib/generators/automation/templates/home.tt +4 -4
- data/lib/generators/automation/templates/login.tt +61 -4
- data/lib/generators/automation/templates/page.tt +13 -7
- data/lib/generators/automation/templates/partials/element.tt +1 -1
- data/lib/generators/automation/templates/partials/home_page_selector.tt +4 -4
- data/lib/generators/automation/templates/partials/initialize_selector.tt +3 -8
- data/lib/generators/automation/templates/partials/pdp_page_selector.tt +4 -4
- data/lib/generators/automation/templates/partials/url_methods.tt +0 -1
- data/lib/generators/automation/templates/partials/visit_method.tt +11 -1
- data/lib/generators/automation/templates/pdp.tt +1 -1
- data/lib/generators/common_generator.rb +12 -0
- data/lib/generators/cucumber/cucumber_generator.rb +36 -0
- data/lib/generators/cucumber/templates/accessibility_feature.tt +5 -0
- data/lib/generators/cucumber/templates/accessibility_steps.tt +21 -0
- data/lib/generators/cucumber/templates/cucumber.tt +8 -1
- data/lib/generators/cucumber/templates/env.tt +6 -4
- data/lib/generators/cucumber/templates/feature.tt +0 -4
- data/lib/generators/cucumber/templates/partials/appium_env.tt +5 -0
- data/lib/generators/cucumber/templates/partials/capybara_env.tt +38 -0
- data/lib/generators/cucumber/templates/partials/capybara_world.tt +6 -0
- data/lib/generators/cucumber/templates/partials/driver_world.tt +1 -4
- data/lib/generators/cucumber/templates/partials/mobile_steps.tt +2 -2
- data/lib/generators/cucumber/templates/partials/selenium_env.tt +22 -35
- data/lib/generators/cucumber/templates/partials/watir_env.tt +20 -1
- data/lib/generators/cucumber/templates/partials/web_steps.tt +10 -15
- data/lib/generators/cucumber/templates/performance_feature.tt +5 -0
- data/lib/generators/cucumber/templates/performance_steps.tt +17 -0
- data/lib/generators/cucumber/templates/steps.tt +2 -2
- data/lib/generators/cucumber/templates/visual_feature.tt +5 -0
- data/lib/generators/cucumber/templates/visual_steps.tt +19 -0
- data/lib/generators/cucumber/templates/world.tt +5 -3
- data/lib/generators/generator.rb +50 -7
- data/lib/generators/helper_generator.rb +39 -9
- data/lib/generators/infrastructure/github_generator.rb +6 -0
- data/lib/generators/infrastructure/templates/github.tt +12 -8
- data/lib/generators/infrastructure/templates/github_appium.tt +108 -0
- data/lib/generators/infrastructure/templates/gitlab.tt +6 -3
- data/lib/generators/invoke_generators.rb +43 -9
- data/lib/generators/menu_generator.rb +122 -11
- data/lib/generators/minitest/minitest_generator.rb +35 -0
- data/lib/generators/minitest/templates/accessibility_test.tt +26 -0
- data/lib/generators/minitest/templates/performance_test.tt +18 -0
- data/lib/generators/minitest/templates/test.tt +64 -0
- data/lib/generators/minitest/templates/visual_test.tt +23 -0
- data/lib/generators/rspec/rspec_generator.rb +16 -4
- data/lib/generators/rspec/templates/accessibility_spec.tt +25 -0
- data/lib/generators/rspec/templates/performance_spec.tt +18 -0
- data/lib/generators/rspec/templates/spec.tt +13 -41
- data/lib/generators/rspec/templates/visual_spec.tt +20 -0
- data/lib/generators/template_renderer/partial_cache.rb +126 -0
- data/lib/generators/template_renderer/partial_resolver.rb +110 -0
- data/lib/generators/template_renderer/template_error.rb +50 -0
- data/lib/generators/template_renderer.rb +106 -0
- data/lib/generators/templates/common/config.tt +2 -2
- data/lib/generators/templates/common/gemfile.tt +36 -9
- data/lib/generators/templates/common/git_ignore.tt +6 -1
- data/lib/generators/templates/common/partials/mobile_config.tt +5 -1
- data/lib/generators/templates/common/partials/web_config.tt +17 -8
- data/lib/generators/templates/common/rakefile.tt +36 -0
- data/lib/generators/templates/common/read_me.tt +43 -91
- data/lib/generators/templates/common/rspec.tt +3 -0
- data/lib/generators/templates/common/ruby_version.tt +1 -0
- data/lib/generators/templates/helpers/allure_helper.tt +13 -2
- data/lib/generators/templates/helpers/browser_helper.tt +13 -2
- data/lib/generators/templates/helpers/capybara_helper.tt +32 -0
- data/lib/generators/templates/helpers/debug_helper.tt +190 -0
- data/lib/generators/templates/helpers/driver_helper.tt +3 -11
- data/lib/generators/templates/helpers/partials/allure_imports.tt +3 -1
- data/lib/generators/templates/helpers/partials/allure_requirements.tt +3 -1
- data/lib/generators/templates/helpers/partials/appium_driver.tt +44 -0
- data/lib/generators/templates/helpers/partials/browserstack_config.tt +13 -0
- data/lib/generators/templates/helpers/partials/debug_diagnostics.tt +7 -0
- data/lib/generators/templates/helpers/partials/debug_start.tt +7 -0
- data/lib/generators/templates/helpers/partials/driver_and_options.tt +5 -115
- data/lib/generators/templates/helpers/partials/quit_driver.tt +3 -1
- data/lib/generators/templates/helpers/partials/screenshot.tt +3 -1
- data/lib/generators/templates/helpers/partials/selenium_driver.tt +26 -0
- data/lib/generators/templates/helpers/partials/video_start.tt +9 -0
- data/lib/generators/templates/helpers/partials/video_stop.tt +4 -0
- data/lib/generators/templates/helpers/performance_helper.tt +57 -0
- data/lib/generators/templates/helpers/spec_helper.tt +72 -10
- data/lib/generators/templates/helpers/test_helper.tt +94 -0
- data/lib/generators/templates/helpers/video_helper.tt +270 -0
- data/lib/generators/templates/helpers/visual_helper.tt +39 -46
- data/lib/llm/client.rb +79 -0
- data/lib/llm/config.rb +57 -0
- data/lib/llm/prompts.rb +84 -0
- data/lib/llm/provider.rb +27 -0
- data/lib/llm/providers/anthropic_provider.rb +43 -0
- data/lib/llm/providers/ollama_provider.rb +56 -0
- data/lib/llm/providers/openai_provider.rb +42 -0
- data/lib/llm/response_parser.rb +67 -0
- data/lib/plugin/plugin.rb +22 -20
- data/lib/plugin/plugin_exposer.rb +16 -38
- data/lib/ruby_raider.rb +51 -11
- data/lib/scaffolding/crud_generator.rb +94 -0
- data/lib/scaffolding/dry_run_presenter.rb +16 -0
- data/lib/scaffolding/name_normalizer.rb +63 -0
- data/lib/scaffolding/page_introspector.rb +45 -0
- data/lib/scaffolding/project_detector.rb +72 -0
- data/lib/scaffolding/scaffold_menu.rb +103 -0
- data/lib/scaffolding/scaffolding.rb +158 -11
- data/lib/scaffolding/templates/component.tt +30 -0
- data/lib/scaffolding/templates/feature.tt +4 -4
- data/lib/scaffolding/templates/helper.tt +15 -1
- data/lib/scaffolding/templates/page_from_url.tt +75 -0
- data/lib/scaffolding/templates/page_object.tt +50 -1
- data/lib/scaffolding/templates/spec.tt +33 -2
- data/lib/scaffolding/templates/spec_from_page.tt +31 -0
- data/lib/scaffolding/templates/spec_from_url.tt +46 -0
- data/lib/scaffolding/templates/steps.tt +17 -5
- data/lib/scaffolding/url_analyzer.rb +179 -0
- data/lib/utilities/desktop_downloader.rb +177 -0
- data/lib/utilities/logo.rb +83 -0
- data/lib/utilities/utilities.rb +53 -20
- data/lib/version +1 -1
- data/ruby_raider.gemspec +1 -0
- data/sig/adopter/adopt_menu.rbs +25 -0
- data/sig/adopter/converters/base_converter.rbs +23 -0
- data/sig/adopter/converters/identity_converter.rbs +16 -0
- data/sig/adopter/migration_plan.rbs +34 -0
- data/sig/adopter/migrator.rbs +21 -0
- data/sig/adopter/plan_builder.rbs +38 -0
- data/sig/adopter/project_analyzer.rbs +39 -0
- data/sig/adopter/project_detector.rbs +26 -0
- data/sig/commands/adopt_commands.rbs +8 -0
- data/sig/commands/loaded_commands.rbs +5 -0
- data/sig/commands/plugin_commands.rbs +9 -0
- data/sig/commands/scaffolding_commands.rbs +28 -0
- data/sig/commands/utility_commands.rbs +21 -0
- data/sig/generators/automation/automation_generator.rbs +20 -0
- data/sig/generators/common_generator.rbs +12 -0
- data/sig/generators/cucumber/cucumber_generator.rbs +16 -0
- data/sig/generators/generator.rbs +40 -0
- data/sig/generators/helper_generator.rbs +18 -0
- data/sig/generators/infrastructure/github_generator.rbs +5 -0
- data/sig/generators/infrastructure/gitlab_generator.rbs +4 -0
- data/sig/generators/invoke_generators.rbs +10 -0
- data/sig/generators/menu_generator.rbs +29 -0
- data/sig/generators/minitest/minitest_generator.rbs +8 -0
- data/sig/generators/rspec/rspec_generator.rbs +8 -0
- data/sig/generators/template_renderer/partial_cache.rbs +20 -0
- data/sig/generators/template_renderer/partial_resolver.rbs +20 -0
- data/sig/generators/template_renderer/template_error.rbs +19 -0
- data/sig/generators/template_renderer.rbs +10 -0
- data/sig/llm/client.rbs +15 -0
- data/sig/llm/config.rbs +20 -0
- data/sig/llm/prompts.rbs +8 -0
- data/sig/llm/provider.rbs +12 -0
- data/sig/llm/providers/anthropic_provider.rbs +16 -0
- data/sig/llm/providers/ollama_provider.rbs +18 -0
- data/sig/llm/providers/openai_provider.rbs +16 -0
- data/sig/llm/response_parser.rbs +13 -0
- data/sig/plugin/plugin.rbs +24 -0
- data/sig/plugin/plugin_exposer.rbs +20 -0
- data/sig/ruby_raider.rbs +15 -0
- data/sig/scaffolding/crud_generator.rbs +16 -0
- data/sig/scaffolding/dry_run_presenter.rbs +4 -0
- data/sig/scaffolding/name_normalizer.rbs +17 -0
- data/sig/scaffolding/page_introspector.rbs +14 -0
- data/sig/scaffolding/project_detector.rbs +14 -0
- data/sig/scaffolding/scaffold_menu.rbs +18 -0
- data/sig/scaffolding/scaffolding.rbs +55 -0
- data/sig/scaffolding/url_analyzer.rbs +28 -0
- data/sig/utilities/desktop_downloader.rbs +23 -0
- data/sig/utilities/logger.rbs +13 -0
- data/sig/utilities/logo.rbs +16 -0
- data/sig/utilities/utilities.rbs +30 -0
- data/sig/vendor/thor.rbs +34 -0
- data/sig/vendor/tty_prompt.rbs +15 -0
- data/spec/adopter/adopt_menu_spec.rb +176 -0
- data/spec/adopter/converters/identity_converter_spec.rb +145 -0
- data/spec/adopter/migration_plan_spec.rb +113 -0
- data/spec/adopter/migrator_spec.rb +277 -0
- data/spec/adopter/plan_builder_spec.rb +298 -0
- data/spec/adopter/project_analyzer_spec.rb +337 -0
- data/spec/adopter/project_detector_spec.rb +295 -0
- data/spec/commands/raider_commands_spec.rb +129 -0
- data/spec/generators/fixtures/templates/test.tt +1 -0
- data/spec/generators/fixtures/templates/test_partial.tt +1 -0
- data/spec/generators/generator_spec.rb +23 -0
- data/spec/generators/template_renderer_spec.rb +298 -0
- data/spec/integration/commands/scaffolding_commands_spec.rb +2 -2
- data/spec/integration/commands/utility_commands_spec.rb +24 -4
- data/spec/integration/content/ci_content_spec.rb +119 -0
- data/spec/integration/content/common_content_spec.rb +288 -0
- data/spec/integration/content/config_content_spec.rb +175 -0
- data/spec/integration/content/content_helper.rb +32 -0
- data/spec/integration/content/gemfile_content_spec.rb +209 -0
- data/spec/integration/content/helper_content_spec.rb +485 -0
- data/spec/integration/content/page_content_spec.rb +259 -0
- data/spec/integration/content/reporter_content_spec.rb +236 -0
- data/spec/integration/content/skip_flags_content_spec.rb +206 -0
- data/spec/integration/content/syntax_validation_spec.rb +30 -0
- data/spec/integration/content/test_content_spec.rb +266 -0
- data/spec/integration/end_to_end_features_spec.rb +690 -0
- data/spec/integration/end_to_end_spec.rb +361 -0
- data/spec/integration/generators/automation_generator_spec.rb +9 -21
- data/spec/integration/generators/axe_addon_spec.rb +150 -0
- data/spec/integration/generators/common_generator_spec.rb +48 -49
- data/spec/integration/generators/config_features_spec.rb +155 -0
- data/spec/integration/generators/cucumber_generator_spec.rb +7 -7
- data/spec/integration/generators/debug_helper_spec.rb +68 -0
- data/spec/integration/generators/github_generator_spec.rb +8 -8
- data/spec/integration/generators/gitlab_generator_spec.rb +8 -8
- data/spec/integration/generators/helpers_generator_spec.rb +70 -44
- data/spec/integration/generators/lighthouse_addon_spec.rb +132 -0
- data/spec/integration/generators/minitest_generator_spec.rb +64 -0
- data/spec/integration/generators/reporter_spec.rb +159 -0
- data/spec/integration/generators/rspec_generator_spec.rb +7 -7
- data/spec/integration/generators/skip_flags_spec.rb +134 -0
- data/spec/integration/generators/visual_addon_spec.rb +148 -0
- data/spec/integration/settings_helper.rb +1 -4
- data/spec/integration/spec_helper.rb +46 -11
- data/spec/llm/client_spec.rb +79 -0
- data/spec/llm/config_spec.rb +92 -0
- data/spec/llm/prompts_spec.rb +49 -0
- data/spec/llm/response_parser_spec.rb +92 -0
- data/spec/menus/adopter_adopt_menu_spec.rb +97 -0
- data/spec/menus/menu_generator_spec.rb +263 -0
- data/spec/scaffolding/name_normalizer_spec.rb +113 -0
- data/spec/scaffolding/page_introspector_spec.rb +82 -0
- data/spec/scaffolding/scaffold_project_detector_spec.rb +104 -0
- data/spec/scaffolding/scaffolding_features_spec.rb +311 -0
- data/spec/scaffolding/url_analyzer_spec.rb +110 -0
- data/spec/system/adopt_matrix_spec.rb +537 -0
- data/spec/system/adopt_spec.rb +225 -0
- data/spec/system/capybara_spec.rb +42 -0
- data/spec/system/selenium_spec.rb +19 -17
- data/spec/system/support/system_test_helper.rb +33 -0
- data/spec/system/watir_spec.rb +19 -17
- data/spec/utilities/desktop_downloader_spec.rb +92 -0
- metadata +193 -18
- data/.github/workflows/push_gem.yml +0 -37
- data/.github/workflows/selenium.yml +0 -22
- data/.github/workflows/watir.yml +0 -22
- data/lib/generators/automation/templates/partials/android_caps.tt +0 -17
- data/lib/generators/automation/templates/partials/cross_platform_caps.tt +0 -25
- data/lib/generators/automation/templates/partials/ios_caps.tt +0 -18
- data/lib/generators/automation/templates/partials/selenium_account.tt +0 -9
- data/lib/generators/automation/templates/partials/selenium_login.tt +0 -34
- data/lib/generators/automation/templates/partials/watir_account.tt +0 -7
- data/lib/generators/automation/templates/partials/watir_login.tt +0 -32
- data/lib/generators/automation/templates/visual_options.tt +0 -16
- data/lib/generators/templates/helpers/visual_spec_helper.tt +0 -35
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Quick Release Guide
|
|
2
|
+
|
|
3
|
+
## TL;DR - One Command Release
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
# Bug fixes: 1.1.4 -> 1.1.5
|
|
7
|
+
bin/release patch
|
|
8
|
+
|
|
9
|
+
# New features: 1.1.4 -> 1.2.0
|
|
10
|
+
bin/release minor
|
|
11
|
+
|
|
12
|
+
# Breaking changes: 1.1.4 -> 2.0.0
|
|
13
|
+
bin/release major
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
**Everything else is automated!**
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## What Happens
|
|
21
|
+
|
|
22
|
+
1. ✅ Script validates & tests locally
|
|
23
|
+
2. ✅ Updates version in `lib/version`
|
|
24
|
+
3. ✅ Creates git commit + tag
|
|
25
|
+
4. ✅ Pushes to GitHub
|
|
26
|
+
5. ✅ GitHub Actions automatically:
|
|
27
|
+
- Runs tests
|
|
28
|
+
- Builds gem
|
|
29
|
+
- Publishes to RubyGems
|
|
30
|
+
- Creates GitHub Release
|
|
31
|
+
|
|
32
|
+
**Duration:** ~3 minutes total
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Before Releasing
|
|
37
|
+
|
|
38
|
+
Ensure:
|
|
39
|
+
- [ ] All changes merged to master
|
|
40
|
+
- [ ] Tests passing: `bundle exec rspec`
|
|
41
|
+
- [ ] Linters passing: `bundle exec rubocop && bundle exec reek`
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Monitor Progress
|
|
46
|
+
|
|
47
|
+
**GitHub Actions:**
|
|
48
|
+
https://github.com/RubyRaider/ruby_raider/actions
|
|
49
|
+
|
|
50
|
+
**GitHub Releases:**
|
|
51
|
+
https://github.com/RubyRaider/ruby_raider/releases
|
|
52
|
+
|
|
53
|
+
**RubyGems:**
|
|
54
|
+
https://rubygems.org/gems/ruby_raider
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## First-Time Setup
|
|
59
|
+
|
|
60
|
+
Add RubyGems API key to GitHub Secrets:
|
|
61
|
+
|
|
62
|
+
1. Get API key:
|
|
63
|
+
```bash
|
|
64
|
+
gem signin
|
|
65
|
+
# Visit https://rubygems.org/profile/edit
|
|
66
|
+
# Copy API key
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
2. Add to GitHub:
|
|
70
|
+
- Go to: Settings → Secrets → Actions
|
|
71
|
+
- Add `RUBYGEMS_API_KEY` secret
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Full Documentation
|
|
76
|
+
|
|
77
|
+
See [RELEASE.md](RELEASE.md) for complete documentation.
|
data/Steepfile
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
target :lib do
|
|
4
|
+
signature 'sig'
|
|
5
|
+
|
|
6
|
+
check 'lib'
|
|
7
|
+
|
|
8
|
+
# External gem stubs (not typed)
|
|
9
|
+
library 'yaml'
|
|
10
|
+
library 'fileutils'
|
|
11
|
+
library 'erb'
|
|
12
|
+
library 'open3'
|
|
13
|
+
library 'timeout'
|
|
14
|
+
library 'uri'
|
|
15
|
+
library 'net-http'
|
|
16
|
+
library 'json'
|
|
17
|
+
library 'logger'
|
|
18
|
+
library 'forwardable'
|
|
19
|
+
|
|
20
|
+
# Configure strictness — start lenient, tighten over time
|
|
21
|
+
configure_code_diagnostics(Steep::Diagnostic::Ruby.lenient)
|
|
22
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<svg width="512" height="512" viewBox="100 100 480 480" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<!-- LEFT HORN -->
|
|
3
|
+
<polygon points="220,248 218,218 168,155" fill="#d4a017"/>
|
|
4
|
+
<polygon points="220,248 168,155 205,230" fill="#e8c840" opacity="0.7"/>
|
|
5
|
+
<polygon points="218,218 168,155 205,230" fill="#b8860b" opacity="0.8"/>
|
|
6
|
+
<line x1="205" y1="230" x2="168" y2="155" stroke="#f5e680" stroke-width="1" opacity="0.4"/>
|
|
7
|
+
<polygon points="222,250 218,218 215,218 219,250" fill="#c9960c" opacity="0.6"/>
|
|
8
|
+
<!-- RIGHT HORN -->
|
|
9
|
+
<polygon points="460,248 462,218 512,155" fill="#d4a017"/>
|
|
10
|
+
<polygon points="460,248 512,155 475,230" fill="#e8c840" opacity="0.7"/>
|
|
11
|
+
<polygon points="462,218 512,155 475,230" fill="#b8860b" opacity="0.8"/>
|
|
12
|
+
<line x1="475" y1="230" x2="512" y2="155" stroke="#f5e680" stroke-width="1" opacity="0.4"/>
|
|
13
|
+
<polygon points="458,250 462,218 465,218 461,250" fill="#c9960c" opacity="0.6"/>
|
|
14
|
+
<!-- PAVILION (chin/jaw) -->
|
|
15
|
+
<polygon points="340,530 250,380 230,340 450,340 430,380" fill="#4d0c1a"/>
|
|
16
|
+
<polygon points="340,530 250,380 290,380" fill="#5c1220"/>
|
|
17
|
+
<polygon points="340,530 290,380 340,370" fill="#6a1525"/>
|
|
18
|
+
<polygon points="340,530 340,370 390,380" fill="#5c1220"/>
|
|
19
|
+
<polygon points="340,530 390,380 430,380" fill="#4d0c1a"/>
|
|
20
|
+
<!-- GIRDLE (visor band) -->
|
|
21
|
+
<rect x="220" y="330" width="240" height="16" rx="2" fill="#2a2a40" opacity="0.85"/>
|
|
22
|
+
<rect x="220" y="330" width="240" height="16" rx="2" fill="none" stroke="#555555" stroke-width="0.5" opacity="0.4"/>
|
|
23
|
+
<g fill="#888888" opacity="0.6">
|
|
24
|
+
<circle cx="255" cy="338" r="3"/><circle cx="285" cy="338" r="3"/>
|
|
25
|
+
<circle cx="315" cy="338" r="3"/><circle cx="345" cy="338" r="3"/>
|
|
26
|
+
<circle cx="375" cy="338" r="3"/><circle cx="405" cy="338" r="3"/>
|
|
27
|
+
</g>
|
|
28
|
+
<g fill="#bbbbbb" opacity="0.3">
|
|
29
|
+
<circle cx="254" cy="337" r="1.3"/><circle cx="284" cy="337" r="1.3"/>
|
|
30
|
+
<circle cx="314" cy="337" r="1.3"/><circle cx="344" cy="337" r="1.3"/>
|
|
31
|
+
<circle cx="374" cy="337" r="1.3"/><circle cx="404" cy="337" r="1.3"/>
|
|
32
|
+
</g>
|
|
33
|
+
<!-- CROWN FACETS -->
|
|
34
|
+
<polygon points="340,130 460,250 460,330 220,330 220,250" fill="#7b1c2a"/>
|
|
35
|
+
<polygon points="340,130 410,195 340,250 270,195" fill="#d4374b"/>
|
|
36
|
+
<polygon points="340,140 390,190 340,235 290,190" fill="#e85a6e" opacity="0.6"/>
|
|
37
|
+
<polygon points="220,250 270,195 220,330" fill="#6a1525"/>
|
|
38
|
+
<polygon points="460,250 410,195 460,330" fill="#6a1525"/>
|
|
39
|
+
<polygon points="270,195 340,250 220,330 220,250" fill="#8c2234" opacity="0.8"/>
|
|
40
|
+
<polygon points="410,195 340,250 460,330 460,250" fill="#8c2234" opacity="0.8"/>
|
|
41
|
+
<!-- TABLE (top facet) -->
|
|
42
|
+
<polygon points="340,155 385,185 340,215 295,185" fill="#ff7088" opacity="0.45"/>
|
|
43
|
+
<!-- Crown highlight -->
|
|
44
|
+
<line x1="280" y1="200" x2="340" y2="140" stroke="#ff9db0" stroke-width="1" opacity="0.3"/>
|
|
45
|
+
<line x1="340" y1="140" x2="400" y2="200" stroke="#ff9db0" stroke-width="1" opacity="0.2"/>
|
|
46
|
+
<!-- EYES -->
|
|
47
|
+
<ellipse cx="300" cy="308" rx="12" ry="8" fill="#1a0a10"/>
|
|
48
|
+
<circle cx="296" cy="305" r="2" fill="#ffffff" opacity="0.6"/>
|
|
49
|
+
<ellipse cx="380" cy="308" rx="12" ry="8" fill="#1a0a10"/>
|
|
50
|
+
<circle cx="376" cy="305" r="2" fill="#ffffff" opacity="0.6"/>
|
|
51
|
+
</svg>
|
data/bin/release
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Automated release script for Ruby Raider
|
|
5
|
+
# Usage: bin/release [major|minor|patch]
|
|
6
|
+
|
|
7
|
+
require 'fileutils'
|
|
8
|
+
|
|
9
|
+
class ReleaseManager
|
|
10
|
+
VERSION_FILE = 'lib/version'
|
|
11
|
+
GEMSPEC_FILE = 'ruby_raider.gemspec'
|
|
12
|
+
|
|
13
|
+
def initialize(bump_type)
|
|
14
|
+
@bump_type = bump_type
|
|
15
|
+
@current_version = read_version
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def run
|
|
19
|
+
validate_clean_repo
|
|
20
|
+
validate_branch
|
|
21
|
+
validate_tests
|
|
22
|
+
|
|
23
|
+
new_version = calculate_new_version
|
|
24
|
+
confirm_release(new_version)
|
|
25
|
+
|
|
26
|
+
update_version(new_version)
|
|
27
|
+
commit_and_tag(new_version)
|
|
28
|
+
push_release
|
|
29
|
+
|
|
30
|
+
success_message(new_version)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def read_version
|
|
36
|
+
File.read(VERSION_FILE).strip
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def validate_clean_repo
|
|
40
|
+
status = `git status --porcelain`.strip
|
|
41
|
+
return if status.empty?
|
|
42
|
+
|
|
43
|
+
puts '❌ Error: Working directory is not clean'
|
|
44
|
+
puts 'Please commit or stash your changes first:'
|
|
45
|
+
puts status
|
|
46
|
+
exit 1
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def validate_branch
|
|
50
|
+
branch = `git branch --show-current`.strip
|
|
51
|
+
return unless branch != 'master' && branch != 'main'
|
|
52
|
+
|
|
53
|
+
puts "⚠️ Warning: You're on branch '#{branch}', not master/main"
|
|
54
|
+
print 'Continue anyway? [y/N] '
|
|
55
|
+
exit 1 unless gets.strip.downcase == 'y'
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def validate_tests
|
|
59
|
+
puts '🧪 Running tests...'
|
|
60
|
+
|
|
61
|
+
# Run unit tests
|
|
62
|
+
unless system('bundle exec rspec spec/generators/ --format progress')
|
|
63
|
+
puts '❌ Unit tests failed'
|
|
64
|
+
exit 1
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Run integration tests (skip slow e2e tests)
|
|
68
|
+
unless system('bundle exec rspec spec/integration/ --tag ~slow --format progress')
|
|
69
|
+
puts '❌ Integration tests failed'
|
|
70
|
+
exit 1
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Run linters
|
|
74
|
+
unless system('bundle exec rubocop')
|
|
75
|
+
puts '❌ RuboCop failed'
|
|
76
|
+
exit 1
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
unless system('bundle exec reek')
|
|
80
|
+
puts '❌ Reek failed'
|
|
81
|
+
exit 1
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
puts '✓ All tests and linters passed'
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def calculate_new_version
|
|
88
|
+
major, minor, patch = @current_version.split('.').map(&:to_i)
|
|
89
|
+
|
|
90
|
+
case @bump_type
|
|
91
|
+
when 'major'
|
|
92
|
+
"#{major + 1}.0.0"
|
|
93
|
+
when 'minor'
|
|
94
|
+
"#{major}.#{minor + 1}.0"
|
|
95
|
+
when 'patch'
|
|
96
|
+
"#{major}.#{minor}.#{patch + 1}"
|
|
97
|
+
else
|
|
98
|
+
puts "❌ Error: Invalid bump type '#{@bump_type}'"
|
|
99
|
+
puts 'Usage: bin/release [major|minor|patch]'
|
|
100
|
+
exit 1
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def confirm_release(new_version)
|
|
105
|
+
puts "\n📦 Release Summary"
|
|
106
|
+
puts " Current version: #{@current_version}"
|
|
107
|
+
puts " New version: #{new_version}"
|
|
108
|
+
puts " Bump type: #{@bump_type}"
|
|
109
|
+
puts "\nThis will:"
|
|
110
|
+
puts " 1. Update lib/version to #{new_version}"
|
|
111
|
+
puts ' 2. Commit changes'
|
|
112
|
+
puts " 3. Create git tag v#{new_version}"
|
|
113
|
+
puts ' 4. Push to GitHub (triggers automated release)'
|
|
114
|
+
puts ' 5. Publish gem to RubyGems (via GitHub Actions)'
|
|
115
|
+
puts ' 6. Create GitHub release with changelog'
|
|
116
|
+
|
|
117
|
+
print "\nProceed with release? [y/N] "
|
|
118
|
+
exit 0 unless gets.strip.downcase == 'y'
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def update_version(new_version)
|
|
122
|
+
puts "\n📝 Updating version to #{new_version}..."
|
|
123
|
+
File.write(VERSION_FILE, "#{new_version}\n")
|
|
124
|
+
puts "✓ Updated #{VERSION_FILE}"
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def commit_and_tag(new_version)
|
|
128
|
+
puts "\n📌 Creating commit and tag..."
|
|
129
|
+
|
|
130
|
+
# Commit version change
|
|
131
|
+
system("git add #{VERSION_FILE}")
|
|
132
|
+
system("git commit -m 'Bump version to #{new_version}'")
|
|
133
|
+
|
|
134
|
+
# Create annotated tag
|
|
135
|
+
system("git tag -a v#{new_version} -m 'Release version #{new_version}'")
|
|
136
|
+
|
|
137
|
+
puts "✓ Created commit and tag v#{new_version}"
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def push_release
|
|
141
|
+
puts "\n🚀 Pushing to GitHub..."
|
|
142
|
+
|
|
143
|
+
# Push commit
|
|
144
|
+
unless system('git push origin HEAD')
|
|
145
|
+
puts '❌ Failed to push commits'
|
|
146
|
+
exit 1
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Push tag (this triggers the release workflow)
|
|
150
|
+
unless system('git push origin --tags')
|
|
151
|
+
puts '❌ Failed to push tags'
|
|
152
|
+
exit 1
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
puts '✓ Pushed to GitHub'
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def success_message(new_version)
|
|
159
|
+
puts "\n#{'=' * 60}"
|
|
160
|
+
puts "🎉 Release #{new_version} initiated successfully!"
|
|
161
|
+
puts '=' * 60
|
|
162
|
+
puts "\nThe GitHub Actions workflow is now:"
|
|
163
|
+
puts ' 1. Running tests'
|
|
164
|
+
puts ' 2. Building the gem'
|
|
165
|
+
puts ' 3. Publishing to RubyGems'
|
|
166
|
+
puts ' 4. Creating GitHub release'
|
|
167
|
+
puts "\nMonitor progress at:"
|
|
168
|
+
puts ' https://github.com/RubyRaider/ruby_raider/actions'
|
|
169
|
+
puts "\nRelease will be available at:"
|
|
170
|
+
puts " https://github.com/RubyRaider/ruby_raider/releases/tag/v#{new_version}"
|
|
171
|
+
puts " https://rubygems.org/gems/ruby_raider/versions/#{new_version}"
|
|
172
|
+
puts "\n✨ Thank you for contributing to Ruby Raider!"
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Main execution
|
|
177
|
+
if ARGV.length != 1
|
|
178
|
+
puts 'Usage: bin/release [major|minor|patch]'
|
|
179
|
+
puts "\nExamples:"
|
|
180
|
+
puts ' bin/release patch # 1.1.4 -> 1.1.5 (bug fixes)'
|
|
181
|
+
puts ' bin/release minor # 1.1.4 -> 1.2.0 (new features)'
|
|
182
|
+
puts ' bin/release major # 1.1.4 -> 2.0.0 (breaking changes)'
|
|
183
|
+
exit 1
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
ReleaseManager.new(ARGV[0]).run
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'tty-prompt'
|
|
4
|
+
require_relative 'project_analyzer'
|
|
5
|
+
require_relative 'plan_builder'
|
|
6
|
+
require_relative 'migrator'
|
|
7
|
+
|
|
8
|
+
module Adopter
|
|
9
|
+
class AdoptMenu
|
|
10
|
+
WEB_AUTOMATIONS = %w[selenium capybara watir].freeze
|
|
11
|
+
TEST_FRAMEWORKS = %w[rspec cucumber minitest].freeze
|
|
12
|
+
CI_PLATFORMS = %w[github gitlab].freeze
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
@prompt = TTY::Prompt.new
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def run
|
|
19
|
+
source_path = ask_source_path
|
|
20
|
+
detection = preview_detection(source_path)
|
|
21
|
+
target_automation = ask_target_automation(detection[:automation])
|
|
22
|
+
target_framework = ask_target_framework(detection[:framework])
|
|
23
|
+
output_path = ask_output_path
|
|
24
|
+
ci_platform = ask_ci_platform(detection[:ci_platform])
|
|
25
|
+
|
|
26
|
+
execute_adoption(
|
|
27
|
+
source_path:,
|
|
28
|
+
output_path:,
|
|
29
|
+
target_automation:,
|
|
30
|
+
target_framework:,
|
|
31
|
+
ci_platform:
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Programmatic entry point for raider_desktop and CLI --parameters
|
|
36
|
+
def self.adopt(params)
|
|
37
|
+
validate_params!(params)
|
|
38
|
+
|
|
39
|
+
analysis = ProjectAnalyzer.new(params[:source_path]).analyze
|
|
40
|
+
plan = PlanBuilder.new(analysis, params).build
|
|
41
|
+
results = Migrator.new(plan).execute
|
|
42
|
+
|
|
43
|
+
{ plan:, results: }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def self.validate_params!(params)
|
|
47
|
+
raise ArgumentError, 'source_path is required' unless params[:source_path]
|
|
48
|
+
raise ArgumentError, 'output_path is required' unless params[:output_path]
|
|
49
|
+
raise ArgumentError, 'target_automation is required' unless params[:target_automation]
|
|
50
|
+
raise ArgumentError, 'target_framework is required' unless params[:target_framework]
|
|
51
|
+
|
|
52
|
+
raise ArgumentError, "target_automation must be one of: #{WEB_AUTOMATIONS.join(', ')}" unless WEB_AUTOMATIONS.include?(params[:target_automation])
|
|
53
|
+
|
|
54
|
+
return if TEST_FRAMEWORKS.include?(params[:target_framework])
|
|
55
|
+
|
|
56
|
+
raise ArgumentError, "target_framework must be one of: #{TEST_FRAMEWORKS.join(', ')}"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
def ask_source_path
|
|
62
|
+
path = @prompt.ask('Enter the path to your existing test project:') do |q|
|
|
63
|
+
q.required true
|
|
64
|
+
q.validate ->(input) { Dir.exist?(input) }
|
|
65
|
+
q.messages[:valid?] = 'Directory does not exist: %<value>s'
|
|
66
|
+
end
|
|
67
|
+
File.expand_path(path)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def preview_detection(source_path)
|
|
71
|
+
detection = ProjectDetector.detect(source_path)
|
|
72
|
+
@prompt.say("\nDetected project settings:")
|
|
73
|
+
@prompt.say(" Automation: #{detection[:automation] || 'unknown'}")
|
|
74
|
+
@prompt.say(" Framework: #{detection[:framework] || 'unknown'}")
|
|
75
|
+
@prompt.say(" Browser: #{detection[:browser] || 'not detected'}")
|
|
76
|
+
@prompt.say(" URL: #{detection[:url] || 'not detected'}")
|
|
77
|
+
@prompt.say(" CI: #{detection[:ci_platform] || 'none'}")
|
|
78
|
+
@prompt.say('')
|
|
79
|
+
detection
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def ask_target_automation(detected)
|
|
83
|
+
default = WEB_AUTOMATIONS.include?(detected) ? detected : nil
|
|
84
|
+
@prompt.select('Select target automation framework:', WEB_AUTOMATIONS.map(&:capitalize),
|
|
85
|
+
default: default&.capitalize) do |menu|
|
|
86
|
+
menu.choice :Quit, -> { exit }
|
|
87
|
+
end.downcase
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def ask_target_framework(detected)
|
|
91
|
+
default = TEST_FRAMEWORKS.include?(detected) ? detected : nil
|
|
92
|
+
@prompt.select('Select target test framework:', TEST_FRAMEWORKS.map(&:capitalize),
|
|
93
|
+
default: default&.capitalize) do |menu|
|
|
94
|
+
menu.choice :Quit, -> { exit }
|
|
95
|
+
end.downcase
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def ask_output_path
|
|
99
|
+
@prompt.ask('Enter the output path for the new Raider project:') do |q|
|
|
100
|
+
q.required true
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def ask_ci_platform(detected)
|
|
105
|
+
choices = [{ name: 'Github Actions', value: 'github' },
|
|
106
|
+
{ name: 'Gitlab CI/CD', value: 'gitlab' },
|
|
107
|
+
{ name: 'No CI', value: nil }]
|
|
108
|
+
default = case detected
|
|
109
|
+
when 'github' then 'Github Actions'
|
|
110
|
+
when 'gitlab' then 'Gitlab CI/CD'
|
|
111
|
+
end
|
|
112
|
+
@prompt.select('Configure CI/CD?', choices, default:)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def execute_adoption(params)
|
|
116
|
+
@prompt.say("\nAdopting project...")
|
|
117
|
+
result = self.class.adopt(params)
|
|
118
|
+
print_results(result[:plan], result[:results])
|
|
119
|
+
rescue MobileProjectError => e
|
|
120
|
+
@prompt.error(e.message)
|
|
121
|
+
rescue StandardError => e
|
|
122
|
+
@prompt.error("Adoption failed: #{e.message}")
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def print_results(plan, results)
|
|
126
|
+
@prompt.say("\nAdoption complete!")
|
|
127
|
+
@prompt.say(" Pages converted: #{results[:pages]}")
|
|
128
|
+
@prompt.say(" Tests converted: #{results[:tests]}")
|
|
129
|
+
@prompt.say(" Features copied: #{results[:features]}")
|
|
130
|
+
@prompt.say(" Steps converted: #{results[:steps]}")
|
|
131
|
+
|
|
132
|
+
unless results[:errors].empty?
|
|
133
|
+
@prompt.warn("\nErrors:")
|
|
134
|
+
results[:errors].each { |e| @prompt.warn(" - #{e}") }
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
unless plan.warnings.empty?
|
|
138
|
+
@prompt.warn("\nWarnings:")
|
|
139
|
+
plan.warnings.each { |w| @prompt.warn(" - #{w}") }
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
@prompt.say("\nOutput: #{plan.output_path}")
|
|
143
|
+
@prompt.say("Run: cd #{plan.output_path} && bundle install")
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Adopter
|
|
4
|
+
module Converters
|
|
5
|
+
class BaseConverter
|
|
6
|
+
RAIDER_BASE_CLASSES = %w[Page BasePage AbstractPage].freeze
|
|
7
|
+
|
|
8
|
+
def convert_page(content, _page_info)
|
|
9
|
+
content
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def convert_test(content, _test_info)
|
|
13
|
+
content
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def ensure_frozen_string_literal(content)
|
|
19
|
+
return content if content.include?('frozen_string_literal')
|
|
20
|
+
|
|
21
|
+
"# frozen_string_literal: true\n\n#{content}"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def update_base_class(content, target_base = 'Page')
|
|
25
|
+
content.gsub(/class\s+(\w+)\s*<\s*([\w:]+)/) do
|
|
26
|
+
class_name = ::Regexp.last_match(1)
|
|
27
|
+
current_base = ::Regexp.last_match(2)
|
|
28
|
+
if raider_compatible_base?(current_base)
|
|
29
|
+
"class #{class_name} < #{target_base}"
|
|
30
|
+
else
|
|
31
|
+
"class #{class_name} < #{current_base}"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def raider_compatible_base?(base_class)
|
|
37
|
+
RAIDER_BASE_CLASSES.include?(base_class) || base_class.include?('Page')
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def update_require_paths(content, target_automation)
|
|
41
|
+
result = content.dup
|
|
42
|
+
result = update_page_requires(result)
|
|
43
|
+
update_helper_requires(result, target_automation)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def update_page_requires(content)
|
|
47
|
+
content.gsub(%r{require_relative\s+['"]\.*/(?:pages?|page_objects)/(\w+)['"]}) do
|
|
48
|
+
page_name = ::Regexp.last_match(1)
|
|
49
|
+
"require_relative '../page_objects/pages/#{page_name}'"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def update_helper_requires(content, target_automation)
|
|
54
|
+
case target_automation
|
|
55
|
+
when 'capybara'
|
|
56
|
+
content.gsub(%r{require_relative\s+['"]\.*/(?:helpers?|support)/(?:driver|browser)_?\w*['"]},
|
|
57
|
+
"require_relative '../helpers/capybara_helper'")
|
|
58
|
+
when 'watir'
|
|
59
|
+
content.gsub(%r{require_relative\s+['"]\.*/(?:helpers?|support)/(?:driver|capybara)_?\w*['"]},
|
|
60
|
+
"require_relative '../helpers/browser_helper'")
|
|
61
|
+
else
|
|
62
|
+
content.gsub(%r{require_relative\s+['"]\.*/(?:helpers?|support)/(?:browser|capybara)_?\w*['"]},
|
|
63
|
+
"require_relative '../helpers/driver_helper'")
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def remove_driver_arg(content)
|
|
68
|
+
content.gsub(/(\w+)\.new\(\s*(?:driver|browser|page)\s*\)/, '\1.new')
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def swap_driver_arg(content, target_arg)
|
|
72
|
+
content.gsub(/(\w+)\.new\(\s*(?:driver|browser|page)\s*\)/, "\\1.new(#{target_arg})")
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def driver_arg_for(target_automation)
|
|
76
|
+
case target_automation
|
|
77
|
+
when 'watir' then 'browser'
|
|
78
|
+
when 'capybara' then nil
|
|
79
|
+
else 'driver'
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'base_converter'
|
|
4
|
+
|
|
5
|
+
module Adopter
|
|
6
|
+
module Converters
|
|
7
|
+
class IdentityConverter < BaseConverter
|
|
8
|
+
def initialize(target_automation)
|
|
9
|
+
super()
|
|
10
|
+
@target_automation = target_automation
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def convert_page(content, _page_info)
|
|
14
|
+
result = content.dup
|
|
15
|
+
result = ensure_frozen_string_literal(result)
|
|
16
|
+
result = update_base_class(result)
|
|
17
|
+
result = add_page_require(result)
|
|
18
|
+
update_page_instantiation(result)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def convert_test(content, _test_info)
|
|
22
|
+
result = content.dup
|
|
23
|
+
result = ensure_frozen_string_literal(result)
|
|
24
|
+
result = update_require_paths(result, @target_automation)
|
|
25
|
+
update_page_instantiation(result)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def convert_step(content)
|
|
29
|
+
result = content.dup
|
|
30
|
+
result = ensure_frozen_string_literal(result)
|
|
31
|
+
result = update_require_paths(result, @target_automation)
|
|
32
|
+
update_page_instantiation(result)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def add_page_require(content)
|
|
38
|
+
return content if content.include?("require_relative '../abstract/page'")
|
|
39
|
+
|
|
40
|
+
content.sub(/^(class\s)/, "require_relative '../abstract/page'\n\n\\1")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def update_page_instantiation(content)
|
|
44
|
+
arg = driver_arg_for(@target_automation)
|
|
45
|
+
if arg
|
|
46
|
+
swap_driver_arg(content, arg)
|
|
47
|
+
else
|
|
48
|
+
remove_driver_arg(content)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Adopter
|
|
4
|
+
class MigrationPlan
|
|
5
|
+
attr_reader :source_path, :output_path, :target_automation, :target_framework,
|
|
6
|
+
:ci_platform, :skeleton_structure, :converted_pages, :converted_tests,
|
|
7
|
+
:converted_features, :converted_steps, :gemfile_additions,
|
|
8
|
+
:config_overrides, :warnings, :manual_actions
|
|
9
|
+
|
|
10
|
+
def initialize(attrs = {})
|
|
11
|
+
@source_path = attrs[:source_path]
|
|
12
|
+
@output_path = attrs[:output_path]
|
|
13
|
+
@target_automation = attrs[:target_automation]
|
|
14
|
+
@target_framework = attrs[:target_framework]
|
|
15
|
+
@ci_platform = attrs[:ci_platform]
|
|
16
|
+
@skeleton_structure = attrs[:skeleton_structure] || {}
|
|
17
|
+
@converted_pages = attrs[:converted_pages] || []
|
|
18
|
+
@converted_tests = attrs[:converted_tests] || []
|
|
19
|
+
@converted_features = attrs[:converted_features] || []
|
|
20
|
+
@converted_steps = attrs[:converted_steps] || []
|
|
21
|
+
@gemfile_additions = attrs[:gemfile_additions] || []
|
|
22
|
+
@config_overrides = attrs[:config_overrides] || {}
|
|
23
|
+
@warnings = attrs[:warnings] || []
|
|
24
|
+
@manual_actions = attrs[:manual_actions] || []
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def to_h
|
|
28
|
+
{
|
|
29
|
+
source_path:,
|
|
30
|
+
output_path:,
|
|
31
|
+
target_automation:,
|
|
32
|
+
target_framework:,
|
|
33
|
+
ci_platform:,
|
|
34
|
+
skeleton_structure:,
|
|
35
|
+
converted_pages: converted_pages.map(&:to_h),
|
|
36
|
+
converted_tests: converted_tests.map(&:to_h),
|
|
37
|
+
converted_features: converted_features.map(&:to_h),
|
|
38
|
+
converted_steps: converted_steps.map(&:to_h),
|
|
39
|
+
gemfile_additions:,
|
|
40
|
+
config_overrides:,
|
|
41
|
+
warnings:,
|
|
42
|
+
manual_actions:
|
|
43
|
+
}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def to_json(*args)
|
|
47
|
+
require 'json'
|
|
48
|
+
to_h.to_json(*args)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def summary
|
|
52
|
+
{
|
|
53
|
+
pages: converted_pages.length,
|
|
54
|
+
tests: converted_tests.length,
|
|
55
|
+
features: converted_features.length,
|
|
56
|
+
steps: converted_steps.length,
|
|
57
|
+
custom_gems: gemfile_additions.length,
|
|
58
|
+
warnings: warnings.length,
|
|
59
|
+
manual_actions: manual_actions.length
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
ConvertedFile = Struct.new(:output_path, :content, :source_file, :conversion_notes, keyword_init: true) do
|
|
65
|
+
def to_h
|
|
66
|
+
{
|
|
67
|
+
output_path:,
|
|
68
|
+
content:,
|
|
69
|
+
source_file:,
|
|
70
|
+
conversion_notes:
|
|
71
|
+
}
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|