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,110 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'template_error'
|
|
4
|
+
|
|
5
|
+
module TemplateRenderer
|
|
6
|
+
# Resolves partial template paths with context-aware searching
|
|
7
|
+
#
|
|
8
|
+
# Resolution strategy:
|
|
9
|
+
# 1. Try relative to calling template: ./partials/{name}.tt
|
|
10
|
+
# 2. Fall back to all Generator.source_paths searching for partials/{name}.tt
|
|
11
|
+
class PartialResolver
|
|
12
|
+
PARTIAL_EXTENSION = '.tt'
|
|
13
|
+
PARTIALS_DIR = 'partials'
|
|
14
|
+
|
|
15
|
+
def initialize(generator_class)
|
|
16
|
+
@generator_class = generator_class
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Resolve a partial name to its absolute file path
|
|
20
|
+
#
|
|
21
|
+
# @param name [String] The partial name (without .tt extension)
|
|
22
|
+
# @param binding [Binding] The binding context from the caller
|
|
23
|
+
# @return [String] Absolute path to the partial file
|
|
24
|
+
# @raise [TemplateNotFoundError] If partial cannot be found
|
|
25
|
+
def resolve(name, binding)
|
|
26
|
+
caller_file = caller_file_from_binding(binding)
|
|
27
|
+
partial_filename = "#{name}#{PARTIAL_EXTENSION}"
|
|
28
|
+
|
|
29
|
+
# Try relative to caller first
|
|
30
|
+
if caller_file
|
|
31
|
+
relative_path = File.join(File.dirname(caller_file), PARTIALS_DIR, partial_filename)
|
|
32
|
+
return File.expand_path(relative_path) if File.exist?(relative_path)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Fall back to searching all source paths
|
|
36
|
+
searched = search_source_paths(partial_filename)
|
|
37
|
+
return searched[:found] if searched[:found]
|
|
38
|
+
|
|
39
|
+
# Not found - raise with helpful error
|
|
40
|
+
raise TemplateNotFoundError.new(
|
|
41
|
+
"Partial '#{name}' not found",
|
|
42
|
+
partial_name: name,
|
|
43
|
+
searched_paths: search_paths(name, binding)
|
|
44
|
+
)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Get all paths that were searched (for error messages)
|
|
48
|
+
def search_paths(name, binding)
|
|
49
|
+
paths = []
|
|
50
|
+
partial_filename = "#{name}#{PARTIAL_EXTENSION}"
|
|
51
|
+
|
|
52
|
+
# Add relative path if available
|
|
53
|
+
caller_file = caller_file_from_binding(binding)
|
|
54
|
+
if caller_file
|
|
55
|
+
relative_path = File.join(File.dirname(caller_file), PARTIALS_DIR, partial_filename)
|
|
56
|
+
paths << relative_path
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Add all source path possibilities (including subdirectories)
|
|
60
|
+
source_paths.each do |source_path|
|
|
61
|
+
paths << File.join(source_path, PARTIALS_DIR, partial_filename)
|
|
62
|
+
|
|
63
|
+
# Also include subdirectories (e.g., templates/common/partials/, templates/helpers/partials/)
|
|
64
|
+
Dir.glob(File.join(source_path, '*', PARTIALS_DIR)).each do |subdir|
|
|
65
|
+
paths << File.join(subdir, partial_filename)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
paths
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
# Extract the calling template file from binding context
|
|
75
|
+
def caller_file_from_binding(binding)
|
|
76
|
+
binding.eval('__FILE__')
|
|
77
|
+
rescue StandardError
|
|
78
|
+
nil
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Search all Generator.source_paths for the partial.
|
|
82
|
+
# Uses a cached directory index to avoid repeated Dir.glob calls.
|
|
83
|
+
def search_source_paths(partial_filename)
|
|
84
|
+
# Check the pre-built index first (fast path)
|
|
85
|
+
partial_dirs.each do |dir|
|
|
86
|
+
full_path = File.join(dir, partial_filename)
|
|
87
|
+
return { found: File.expand_path(full_path), searched: [full_path] } if File.exist?(full_path)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
{ found: nil, searched: [] }
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Get all configured source paths from the generator class
|
|
94
|
+
def source_paths
|
|
95
|
+
@source_paths ||= @generator_class.source_paths || []
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Pre-built index of all directories that could contain partials.
|
|
99
|
+
# Scanned once via Dir.glob, then reused for every partial lookup.
|
|
100
|
+
def partial_dirs
|
|
101
|
+
@partial_dirs ||= source_paths.flat_map do |source_path|
|
|
102
|
+
dirs = []
|
|
103
|
+
direct = File.join(source_path, PARTIALS_DIR)
|
|
104
|
+
dirs << direct if File.directory?(direct)
|
|
105
|
+
Dir.glob(File.join(source_path, '*', PARTIALS_DIR)).each { |d| dirs << d }
|
|
106
|
+
dirs
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module TemplateRenderer
|
|
4
|
+
# Base error class for all template-related errors
|
|
5
|
+
class TemplateError < StandardError
|
|
6
|
+
attr_reader :partial_name, :searched_paths, :original_error
|
|
7
|
+
|
|
8
|
+
def initialize(message, partial_name: nil, searched_paths: nil, original_error: nil)
|
|
9
|
+
@partial_name = partial_name
|
|
10
|
+
@searched_paths = searched_paths || []
|
|
11
|
+
@original_error = original_error
|
|
12
|
+
super(message)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Raised when a partial template cannot be found
|
|
17
|
+
class TemplateNotFoundError < TemplateError
|
|
18
|
+
def to_s
|
|
19
|
+
message_parts = ["Partial '#{@partial_name}' not found."]
|
|
20
|
+
|
|
21
|
+
if @searched_paths.any?
|
|
22
|
+
message_parts << "\nSearched in:"
|
|
23
|
+
message_parts.concat(@searched_paths.map { |path| " - #{path}" })
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
message_parts.join("\n")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Raised when a template has syntax errors or rendering fails
|
|
31
|
+
class TemplateRenderError < TemplateError
|
|
32
|
+
def initialize(message, partial_name:, original_error: nil)
|
|
33
|
+
super(message, partial_name:, original_error:)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def to_s
|
|
37
|
+
message_parts = ["Error rendering partial '#{@partial_name}': #{super()}"]
|
|
38
|
+
|
|
39
|
+
if @original_error
|
|
40
|
+
message_parts << "\nOriginal error: #{@original_error.class}: #{@original_error.message}"
|
|
41
|
+
if @original_error.backtrace
|
|
42
|
+
message_parts << "\nBacktrace:"
|
|
43
|
+
message_parts.concat(@original_error.backtrace.first(5).map { |line| " #{line}" })
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
message_parts.join("\n")
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'template_renderer/partial_cache'
|
|
4
|
+
require_relative 'template_renderer/partial_resolver'
|
|
5
|
+
require_relative 'template_renderer/template_error'
|
|
6
|
+
|
|
7
|
+
# Template rendering module for Ruby Raider generators
|
|
8
|
+
#
|
|
9
|
+
# Provides a clean partial() helper for including ERB templates with:
|
|
10
|
+
# - Automatic caching of compiled ERB objects (10x performance improvement)
|
|
11
|
+
# - Context-aware path resolution (relative to caller, then all source_paths)
|
|
12
|
+
# - Helpful error messages when partials are missing
|
|
13
|
+
# - Flexible whitespace handling (trim_mode, strip options)
|
|
14
|
+
#
|
|
15
|
+
# Usage in templates:
|
|
16
|
+
# <%= partial('screenshot') %> # Default: trim_mode: '-', no strip
|
|
17
|
+
# <%= partial('screenshot', strip: true) %> # With .strip!
|
|
18
|
+
# <%= partial('screenshot', trim: false) %> # No trim_mode
|
|
19
|
+
# <%= partial('driver_config', trim_mode: '<>') %> # Custom trim_mode
|
|
20
|
+
#
|
|
21
|
+
# The partial() method automatically has access to all generator instance
|
|
22
|
+
# variables and methods (cucumber?, mobile?, selenium?, etc.) through binding.
|
|
23
|
+
module TemplateRenderer
|
|
24
|
+
# Render a partial template with caching and smart path resolution
|
|
25
|
+
#
|
|
26
|
+
# @param name [String] Partial name without .tt extension (e.g., 'screenshot')
|
|
27
|
+
# @param options [Hash] Rendering options
|
|
28
|
+
# @option options [String, nil] :trim_mode ERB trim mode (default: '-')
|
|
29
|
+
# - '-' : Trim lines ending with -%>
|
|
30
|
+
# - '<>' : Omit newlines for lines starting with <% and ending with %>
|
|
31
|
+
# - nil : No trimming
|
|
32
|
+
# @option options [Boolean] :strip Whether to call .strip! on result (default: false)
|
|
33
|
+
# @option options [Boolean] :trim Whether to use trim_mode (default: true)
|
|
34
|
+
#
|
|
35
|
+
# @return [String] Rendered template content
|
|
36
|
+
#
|
|
37
|
+
# @example Basic usage
|
|
38
|
+
# <%= partial('screenshot') %>
|
|
39
|
+
#
|
|
40
|
+
# @example With strip
|
|
41
|
+
# <%= partial('screenshot', strip: true) %>
|
|
42
|
+
#
|
|
43
|
+
# @example No trim mode
|
|
44
|
+
# <%= partial('quit_driver', trim: false) %>
|
|
45
|
+
#
|
|
46
|
+
# @raise [TemplateNotFoundError] If partial cannot be found
|
|
47
|
+
# @raise [TemplateRenderError] If rendering fails
|
|
48
|
+
def partial(name, options = {})
|
|
49
|
+
# Default options
|
|
50
|
+
options = {
|
|
51
|
+
trim_mode: '-',
|
|
52
|
+
strip: false,
|
|
53
|
+
trim: true
|
|
54
|
+
}.merge(options)
|
|
55
|
+
|
|
56
|
+
# Handle trim: false by setting trim_mode to nil
|
|
57
|
+
options[:trim_mode] = nil if options[:trim] == false
|
|
58
|
+
|
|
59
|
+
# Render the partial through the cache
|
|
60
|
+
result = self.class.template_renderer.render_partial(name, binding, options)
|
|
61
|
+
|
|
62
|
+
# Apply strip if requested
|
|
63
|
+
options[:strip] ? result.strip : result
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Module hook for including in classes
|
|
67
|
+
def self.included(base)
|
|
68
|
+
base.extend(ClassMethods)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Class methods added to the including class
|
|
72
|
+
module ClassMethods
|
|
73
|
+
# Get the shared template renderer instance
|
|
74
|
+
# Each generator class gets its own cache instance
|
|
75
|
+
def template_renderer
|
|
76
|
+
@template_renderer ||= PartialCache.new(self)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Clear the template cache (useful for testing)
|
|
80
|
+
# Clears cache for this class and all subclasses
|
|
81
|
+
def clear_template_cache
|
|
82
|
+
@template_renderer&.clear
|
|
83
|
+
@template_renderer = nil
|
|
84
|
+
subclasses.each do |subclass|
|
|
85
|
+
subclass.clear_template_cache if subclass.respond_to?(:clear_template_cache)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Get cache statistics (useful for debugging)
|
|
90
|
+
# Aggregates stats across this class and all subclasses
|
|
91
|
+
def template_cache_stats
|
|
92
|
+
own = @template_renderer&.stats || { size: 0, entries: [], memory_estimate: 0 }
|
|
93
|
+
subclasses.each do |subclass|
|
|
94
|
+
next unless subclass.respond_to?(:template_cache_stats)
|
|
95
|
+
|
|
96
|
+
sub_stats = subclass.instance_variable_get(:@template_renderer)&.stats
|
|
97
|
+
next unless sub_stats
|
|
98
|
+
|
|
99
|
+
own[:size] += sub_stats[:size]
|
|
100
|
+
own[:entries].concat(sub_stats[:entries])
|
|
101
|
+
own[:memory_estimate] += sub_stats[:memory_estimate]
|
|
102
|
+
end
|
|
103
|
+
own
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<% if mobile? -%>
|
|
2
|
-
<%=
|
|
2
|
+
<%= partial('mobile_config', trim: false) %>
|
|
3
3
|
<% else -%>
|
|
4
|
-
<%=
|
|
4
|
+
<%= partial('web_config') %>
|
|
5
5
|
<% end -%>
|
|
@@ -1,38 +1,61 @@
|
|
|
1
1
|
source 'https://rubygems.org'
|
|
2
2
|
|
|
3
|
+
ruby '~> <%= ruby_version %>.0'
|
|
4
|
+
|
|
3
5
|
gem 'activesupport'
|
|
4
6
|
<% if mobile? %>
|
|
5
7
|
gem 'appium_lib'
|
|
6
8
|
gem 'appium_console'
|
|
7
9
|
<% end %>
|
|
10
|
+
<%- if allure_reporter? -%>
|
|
8
11
|
<%- if cucumber? -%>
|
|
9
|
-
gem 'allure-cucumber', '2.
|
|
12
|
+
gem 'allure-cucumber', '2.28.0'
|
|
13
|
+
<%- elsif minitest? -%>
|
|
14
|
+
gem 'allure-ruby-commons', '2.28.0'
|
|
10
15
|
<%- else -%>
|
|
11
|
-
gem 'allure-rspec', '2.
|
|
12
|
-
gem 'allure-ruby-commons', '2.
|
|
16
|
+
gem 'allure-rspec', '2.28.0'
|
|
17
|
+
gem 'allure-ruby-commons', '2.28.0'
|
|
18
|
+
<%- end -%>
|
|
19
|
+
<%- end -%>
|
|
20
|
+
<%- if capybara? -%>
|
|
21
|
+
gem 'capybara'
|
|
22
|
+
gem 'selenium-webdriver'
|
|
13
23
|
<%- end -%>
|
|
14
|
-
<%- if
|
|
24
|
+
<%- if axe_addon? -%>
|
|
25
|
+
<%- if minitest? -%>
|
|
26
|
+
gem 'axe-core-minitest'
|
|
27
|
+
<%- else -%>
|
|
15
28
|
gem 'axe-core-rspec'
|
|
29
|
+
<%- end -%>
|
|
16
30
|
gem 'axe-core-selenium'
|
|
17
31
|
<%- end -%>
|
|
18
|
-
<%- if
|
|
19
|
-
gem '
|
|
20
|
-
gem 'eyes_universal', '~> 3.3', '>= 3.3.1'
|
|
32
|
+
<%- if visual_addon? -%>
|
|
33
|
+
gem 'chunky_png'
|
|
21
34
|
<%- end -%>
|
|
22
|
-
<%- unless visual? -%>
|
|
23
35
|
gem 'parallel_split_test'
|
|
24
36
|
gem 'parallel_tests'
|
|
25
|
-
<%- end -%>
|
|
26
37
|
gem 'rake'
|
|
27
38
|
gem 'reek'
|
|
39
|
+
<%- if rspec? -%>
|
|
40
|
+
gem 'rspec-retry'
|
|
41
|
+
<%- end -%>
|
|
42
|
+
<%- if junit_reporter? && rspec? -%>
|
|
43
|
+
gem 'rspec_junit_formatter'
|
|
44
|
+
<%- end -%>
|
|
28
45
|
gem '<%= framework %>'
|
|
29
46
|
<%- if cucumber? -%>
|
|
30
47
|
gem 'rspec'
|
|
31
48
|
<%- end -%>
|
|
49
|
+
<%- if minitest? -%>
|
|
50
|
+
gem 'minitest-reporters'
|
|
51
|
+
<%- end -%>
|
|
32
52
|
gem 'rubocop'
|
|
33
53
|
<%- if rspec? -%>
|
|
34
54
|
gem 'rubocop-rspec'
|
|
35
55
|
<%- end -%>
|
|
56
|
+
<%- if minitest? -%>
|
|
57
|
+
gem 'rubocop-minitest'
|
|
58
|
+
<%- end -%>
|
|
36
59
|
gem 'ruby_raider', '~> 1.1.0'
|
|
37
60
|
<%- if selenium_based? %>
|
|
38
61
|
gem 'selenium-webdriver'
|
|
@@ -40,3 +63,7 @@ gem 'selenium-webdriver'
|
|
|
40
63
|
<%- if watir? -%>
|
|
41
64
|
gem 'watir'
|
|
42
65
|
<%- end -%>
|
|
66
|
+
<%- if web? -%>
|
|
67
|
+
gem 'debug', '>= 1.0'
|
|
68
|
+
gem 'pry'
|
|
69
|
+
<%- end -%>
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
browser: chrome
|
|
2
|
-
url: 'https://
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
:
|
|
7
|
-
:implicit: 10000 # 10 seconds
|
|
8
|
-
<% end -%>
|
|
2
|
+
url: 'https://raider-test-site.onrender.com/'
|
|
3
|
+
timeout: 10 # seconds — used for implicit waits and max wait time
|
|
4
|
+
viewport:
|
|
5
|
+
width: 1920
|
|
6
|
+
height: 1080
|
|
9
7
|
|
|
10
8
|
browser_arguments:
|
|
11
9
|
chrome:
|
|
@@ -15,4 +13,15 @@ browser_arguments:
|
|
|
15
13
|
- search-engine-choice-country
|
|
16
14
|
firefox:
|
|
17
15
|
- acceptInsecureCerts
|
|
18
|
-
- no-sandbox
|
|
16
|
+
- no-sandbox
|
|
17
|
+
|
|
18
|
+
video:
|
|
19
|
+
enabled: false
|
|
20
|
+
strategy: auto # auto, cdp, or screen
|
|
21
|
+
|
|
22
|
+
debug:
|
|
23
|
+
enabled: false # also toggled by DEBUG=true env var
|
|
24
|
+
console_logs: true # capture browser console logs on failure
|
|
25
|
+
action_logging: true # log driver actions with timestamps
|
|
26
|
+
network_logging: true # capture HTTP requests on failure (Chrome/Edge only)
|
|
27
|
+
log_dir: 'debug_logs'
|
|
@@ -2,3 +2,39 @@ desc 'Print Ruby Raider version'
|
|
|
2
2
|
task :raider do
|
|
3
3
|
system 'raider version'
|
|
4
4
|
end
|
|
5
|
+
<%- if rspec? -%>
|
|
6
|
+
|
|
7
|
+
require 'rspec/core/rake_task'
|
|
8
|
+
|
|
9
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
10
|
+
RSpec::Core::RakeTask.new(:smoke) do |t|
|
|
11
|
+
t.rspec_opts = '--tag smoke'
|
|
12
|
+
end
|
|
13
|
+
RSpec::Core::RakeTask.new(:regression) do |t|
|
|
14
|
+
t.rspec_opts = '--tag regression'
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
task default: :spec
|
|
18
|
+
<%- elsif cucumber? -%>
|
|
19
|
+
|
|
20
|
+
require 'cucumber/rake/task'
|
|
21
|
+
|
|
22
|
+
Cucumber::Rake::Task.new(:features)
|
|
23
|
+
Cucumber::Rake::Task.new(:smoke) do |t|
|
|
24
|
+
t.cucumber_opts = '--tags @smoke'
|
|
25
|
+
end
|
|
26
|
+
Cucumber::Rake::Task.new(:regression) do |t|
|
|
27
|
+
t.cucumber_opts = '--tags @regression'
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
task default: :features
|
|
31
|
+
<%- elsif minitest? -%>
|
|
32
|
+
|
|
33
|
+
require 'rake/testtask'
|
|
34
|
+
|
|
35
|
+
Rake::TestTask.new(:test) do |t|
|
|
36
|
+
t.test_files = FileList['test/**/test_*.rb']
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
task default: :test
|
|
40
|
+
<%- end -%>
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
<br />
|
|
5
5
|
<div align="center">
|
|
6
6
|
<a href="https://github.com/RubyRaider/ruby_raider">
|
|
7
|
-
<img src="https://
|
|
7
|
+
<img src="https://www.ruby-raider.com/assets/icon-DYY74ofR.png" alt="Logo" style="width:200px;">
|
|
8
8
|
</a>
|
|
9
9
|
<p align="center">
|
|
10
|
-
<a href="https://github.com/RubyRaider/ruby_raider#getting-started"><strong>Explore the docs
|
|
10
|
+
<a href="https://github.com/RubyRaider/ruby_raider#getting-started"><strong>Explore the docs</strong></a>
|
|
11
11
|
<br />
|
|
12
12
|
<br />
|
|
13
13
|
<a href="https://rubygems.org/gems/ruby_raider">Rubygems</a>
|
|
@@ -21,119 +21,71 @@
|
|
|
21
21
|
|
|
22
22
|
## What is Ruby Raider?
|
|
23
23
|
|
|
24
|
-
Ruby Raider is a generator and scaffolding gem to make UI test automation easier
|
|
24
|
+
Ruby Raider is a generator and scaffolding gem to make UI test automation easier.
|
|
25
25
|
|
|
26
|
-
###
|
|
26
|
+
### Supported Frameworks
|
|
27
27
|
|
|
28
|
-
| Web Testing Framework |
|
|
29
|
-
|
|
30
|
-
| Cucumber and Selenium | Cucumber
|
|
31
|
-
|
|
|
32
|
-
| Cucumber and Watir |
|
|
33
|
-
|
|
|
34
|
-
|
|
|
35
|
-
|
|
|
28
|
+
| Web Testing Framework | Mobile Testing Framework |
|
|
29
|
+
|-----------------------|------------------------------------|
|
|
30
|
+
| Cucumber and Selenium | Cucumber and Appium for iOS |
|
|
31
|
+
| RSpec and Selenium | RSpec and Appium for iOS |
|
|
32
|
+
| Cucumber and Watir | Cucumber and Appium for Android |
|
|
33
|
+
| RSpec and Watir | RSpec and Appium for Android |
|
|
34
|
+
| Cucumber and Capybara | Cucumber and Appium Cross-platform |
|
|
35
|
+
| RSpec and Capybara | RSpec and Appium Cross-platform |
|
|
36
|
+
| Minitest and Selenium | Minitest and Appium for iOS |
|
|
37
|
+
| Minitest and Watir | Minitest and Appium for Android |
|
|
38
|
+
| Minitest and Capybara | Minitest and Appium Cross-platform |
|
|
36
39
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
**Optional add-ons for web projects:**
|
|
41
|
+
- **Accessibility testing (axe)**: `--accessibility` flag
|
|
42
|
+
- **Visual regression testing (chunky_png)**: `--visual` flag
|
|
43
|
+
- **Performance auditing (Lighthouse)**: `--performance` flag
|
|
40
44
|
|
|
41
|
-
|
|
42
|
-
raider u start_appium
|
|
43
|
-
appium --base /wd/hub
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
***In order to run the visual tests with applitools, you need to create an account and get your api key, you can read
|
|
47
|
-
more [here](https://applitools.com/docs/topics/overview/obtain-api-key.html#:~:text=If%20you%20already%20have%20an,Your%20key%20will%20be%20displayed.)
|
|
48
|
-
.***
|
|
45
|
+
***The web tests run against the [Raider Test Store](https://raider-test-site.onrender.com/).***
|
|
49
46
|
|
|
50
|
-
***To
|
|
51
|
-
you can also set the optional OPENAI_ORGANIZATION_ID if you have an organization***
|
|
47
|
+
***To run Appium tests, download the example [app](https://github.com/RaiderHQ/raider_test_app) and start the server:***
|
|
52
48
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
```bash
|
|
50
|
+
raider u start_appium
|
|
51
|
+
```
|
|
56
52
|
|
|
57
|
-
|
|
53
|
+
This works on all platforms (Mac OS, Linux and Windows).
|
|
58
54
|
|
|
59
|
-
|
|
55
|
+
## Getting Started
|
|
60
56
|
|
|
61
|
-
```
|
|
57
|
+
```bash
|
|
62
58
|
gem install ruby_raider
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
**Then do:**
|
|
66
|
-
|
|
67
|
-
```ruby
|
|
68
59
|
raider new [name_of_project]
|
|
69
60
|
```
|
|
70
61
|
|
|
71
|
-
|
|
72
|
-
selected.
|
|
62
|
+
Or with parameters:
|
|
73
63
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
If you already know which frameworks you want to use, you can do:
|
|
77
|
-
|
|
78
|
-
```ruby
|
|
64
|
+
```bash
|
|
79
65
|
raider new [name_of_project] -p framework:[framework] automation:[automation_type]
|
|
80
66
|
```
|
|
81
67
|
|
|
82
|
-
|
|
68
|
+
### Commands
|
|
83
69
|
|
|
84
|
-
```ruby
|
|
85
|
-
raider new test_project -p framework:rspec automation:selenium
|
|
86
70
|
```
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
Commands :
|
|
94
|
-
raider generate # Provides access to all the scaffolding commands
|
|
95
|
-
raider help [COMMAND] # Describe available commands or one specific command
|
|
96
|
-
raider new [PROJECT_NAME] # Creates a new framework based on settings picked
|
|
97
|
-
raider utility # Provides access to all the utility commands
|
|
98
|
-
raider version # It shows the version of Ruby Raider you are currently using
|
|
71
|
+
raider generate # Scaffolding commands
|
|
72
|
+
raider utility # Utility commands
|
|
73
|
+
raider plugin_manager # Plugin management
|
|
74
|
+
raider new [NAME] # Create new project
|
|
75
|
+
raider version # Show version
|
|
76
|
+
raider help [COMMAND] # Describe commands
|
|
99
77
|
```
|
|
100
78
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
* g for generate
|
|
104
|
-
* n for new
|
|
105
|
-
* u for utility
|
|
106
|
-
* v for version
|
|
107
|
-
|
|
108
|
-
### Scaffolding Commands
|
|
109
|
-
|
|
110
|
-
Ruby Raider also supports scaffolding:
|
|
111
|
-
|
|
112
|
-
* To create a new page object you do: ```raider g page [PAGE_NAME]```
|
|
113
|
-
* To create a new spec you do: ```raider g spec [SPEC_NAME]```
|
|
114
|
-
* To create a new feature you do: ```raider g feature [FEATURE_NAME]```
|
|
115
|
-
* To create a new steps definition you do: ```raider g steps [STEPS_NAME]```
|
|
116
|
-
* To create both a page/spec or a page/feature/steps you do: ```raider g scaffold [SCAFFOLD_NAME]```
|
|
79
|
+
Shortcuts: `g` (generate), `n` (new), `u` (utility), `v` (version), `pm` (plugin_manager)
|
|
117
80
|
|
|
118
|
-
|
|
119
|
-
specs.
|
|
81
|
+
### Scaffolding
|
|
120
82
|
|
|
121
|
-
If you want to set the default path for the creation of your features, helpers and specs:
|
|
122
|
-
|
|
123
|
-
```ruby
|
|
124
|
-
raider u path [PATH_NAME] - -feature or f
|
|
125
|
-
raider u path [PATH_NAME] - -spec or s
|
|
126
|
-
raider u path [PATH_NAME] - -helper or h
|
|
127
83
|
```
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
To initialise Appium server run this command:
|
|
134
|
-
|
|
135
|
-
```ruby
|
|
136
|
-
raider u start_appium
|
|
84
|
+
raider g page [NAME] # Create page object
|
|
85
|
+
raider g spec [NAME] # Create RSpec test
|
|
86
|
+
raider g feature [NAME] # Create Cucumber feature
|
|
87
|
+
raider g steps [NAME] # Create step definitions
|
|
88
|
+
raider g scaffold [NAME] # Create page + test + steps
|
|
137
89
|
```
|
|
138
90
|
|
|
139
91
|
### Sponsors
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= ruby_version %>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
<%=-
|
|
4
|
-
<%- allure =
|
|
3
|
+
<%=- partial('allure_requirements', trim: false, strip: true) -%>
|
|
4
|
+
<%- allure = partial('allure_imports', trim: false, strip: true) -%>
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
module AllureHelper
|
|
@@ -21,6 +21,17 @@ module AllureHelper
|
|
|
21
21
|
test_case: true
|
|
22
22
|
)
|
|
23
23
|
end
|
|
24
|
+
|
|
25
|
+
def add_video(name, file)
|
|
26
|
+
return unless file && File.exist?(file)
|
|
27
|
+
|
|
28
|
+
Allure.add_attachment(
|
|
29
|
+
name: "Recording: #{name}",
|
|
30
|
+
source: File.new(file),
|
|
31
|
+
type: 'video/mp4',
|
|
32
|
+
test_case: true
|
|
33
|
+
)
|
|
34
|
+
end
|
|
24
35
|
<%- if rspec? -%>
|
|
25
36
|
|
|
26
37
|
def formatter
|