Skip to content

Commit ecea074

Browse files
justin808claude
andcommitted
Refactor e2e.rake and add demo_name validation
This commit includes multiple improvements: E2E Testing Refactoring: - Extract server management logic from e2e.rake into dedicated classes - Create E2eTestRunner class to orchestrate tests across modes - Create ServerManager class to handle server lifecycle - Add 27 comprehensive RSpec tests for the new classes - Reduce e2e.rake from 123 lines to 33 lines DemoCreator Improvements: - Add comprehensive demo_name validation with input sanitization - Add dry-run logging for file deletion operations - Clarify Playwright installation logic with better structure - Remove redundant || false from prerelease flags - Refactor completion messages into dedicated methods - Fix Metrics/AbcSize violations through method extraction - Add 9 new validation tests for demo_name Install Generator: - Add error handling for cypress_on_rails:install failures - Provide clear guidance when generator fails RuboCop Configuration: - Update TargetRubyVersion from 3.0 to 3.1 - Update to use require instead of plugins (deprecated) - Remove unused Rails cops configuration All tests pass (200 examples, 0 failures) All RuboCop offenses resolved 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 613d1ac commit ecea074

File tree

10 files changed

+635
-174
lines changed

10 files changed

+635
-174
lines changed

.rubocop.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# RuboCop configuration for React on Rails Demos monorepo
22

3-
plugins:
3+
require:
44
- rubocop-performance
55

66
AllCops:
77
NewCops: enable
88
SuggestExtensions: false
9-
TargetRubyVersion: 3.0
9+
TargetRubyVersion: 3.1
1010
Exclude:
1111
- 'node_modules/**/*'
1212
- 'demos/**/node_modules/**/*'
@@ -40,8 +40,6 @@ Metrics/ClassLength:
4040
# Allow more complex methods for demo scaffolding
4141
Metrics/AbcSize:
4242
Max: 25
43-
Exclude:
44-
- 'lib/demo_scripts/demo_creator.rb'
4543

4644
Metrics/CyclomaticComplexity:
4745
Max: 10

lib/demo_scripts/demo_creator.rb

Lines changed: 99 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ def initialize(
2424
skip_playwright: false,
2525
typescript: false
2626
)
27+
validate_demo_name!(demo_name)
2728
@demo_name = demo_name
2829
@scratch = scratch
2930
@skip_playwright = skip_playwright
@@ -49,14 +50,7 @@ def initialize(
4950
def create!
5051
run_pre_flight_checks unless @skip_pre_flight
5152

52-
puts ''
53-
if @dry_run
54-
puts '🔍 DRY RUN MODE - Commands that would be executed:'
55-
else
56-
puts "🚀 Creating new React on Rails demo: #{@demo_name}"
57-
end
58-
puts ''
59-
53+
print_start_message
6054
@creation_start_time = Time.now
6155

6256
create_rails_app
@@ -67,19 +61,7 @@ def create!
6761
install_shakapacker
6862
install_react_on_rails
6963
install_demo_common_generator
70-
71-
# Install Playwright browsers early for non-GitHub sources
72-
# (dependencies are already installed via demo_common generator)
73-
install_playwright_browsers unless @skip_playwright || using_github_sources?
74-
75-
# Build GitHub packages and reinstall dependencies
76-
# This updates package.json and runs npm install again
77-
build_github_npm_packages if using_github_sources?
78-
79-
# Install Playwright browsers after GitHub package building
80-
# (npm dependencies are now ready after rebuild)
81-
install_playwright_browsers if !@skip_playwright && using_github_sources?
82-
64+
handle_playwright_installation
8365
create_readme
8466
cleanup_unnecessary_files
8567
create_metadata_file
@@ -90,6 +72,39 @@ def create!
9072

9173
private
9274

75+
def print_start_message
76+
puts ''
77+
if @dry_run
78+
puts '🔍 DRY RUN MODE - Commands that would be executed:'
79+
else
80+
puts "🚀 Creating new React on Rails demo: #{@demo_name}"
81+
end
82+
puts ''
83+
end
84+
85+
def handle_playwright_installation
86+
# Install Playwright browsers at the right time:
87+
# - For npm packages: install after demo_common generator (dependencies already ready)
88+
# - For GitHub sources: install after building packages (dependencies ready after rebuild)
89+
return if @skip_playwright
90+
91+
install_playwright_browsers unless using_github_sources?
92+
build_github_npm_packages if using_github_sources?
93+
install_playwright_browsers if using_github_sources?
94+
end
95+
96+
def validate_demo_name!(name)
97+
raise ArgumentError, 'Demo name cannot be empty' if name.nil? || name.strip.empty?
98+
99+
raise ArgumentError, 'Demo name cannot contain slashes' if name.include?('/')
100+
101+
raise ArgumentError, 'Demo name cannot start with . or _' if name.start_with?('.', '_')
102+
103+
return if name.match?(/^[a-zA-Z0-9_-]+$/)
104+
105+
raise ArgumentError, 'Demo name can only contain alphanumeric characters, hyphens, and underscores'
106+
end
107+
93108
def run_pre_flight_checks
94109
PreFlightChecks.new(
95110
demo_dir: @demo_dir,
@@ -349,8 +364,6 @@ def install_react_on_rails
349364
end
350365

351366
def cleanup_conflicting_files
352-
return if @dry_run
353-
354367
# Only remove Procfile.* files - React on Rails will overwrite shakapacker.yml with --force
355368
conflicting_files = [
356369
'Procfile.dev',
@@ -360,7 +373,11 @@ def cleanup_conflicting_files
360373

361374
conflicting_files.each do |file|
362375
file_path = File.join(@demo_dir, file)
363-
if File.exist?(file_path)
376+
next unless File.exist?(file_path)
377+
378+
if @dry_run
379+
puts " [DRY RUN] Would remove conflicting file: #{file}"
380+
else
364381
File.delete(file_path)
365382
puts " Removed conflicting file: #{file}"
366383
end
@@ -481,8 +498,8 @@ def generate_metadata_yaml
481498
'options' => {
482499
'rails_args' => @rails_args,
483500
'react_on_rails_args' => @react_on_rails_args,
484-
'shakapacker_prerelease' => @config.shakapacker_version&.start_with?('github:') || false,
485-
'react_on_rails_prerelease' => @config.react_on_rails_version&.start_with?('github:') || false
501+
'shakapacker_prerelease' => @config.shakapacker_version&.start_with?('github:'),
502+
'react_on_rails_prerelease' => @config.react_on_rails_version&.start_with?('github:')
486503
}.compact,
487504
'command' => reconstruct_command,
488505
'ruby_version' => RUBY_VERSION,
@@ -530,45 +547,65 @@ def print_completion_message
530547
puts ''
531548
puts '=' * 80
532549
puts ''
533-
if @dry_run
534-
puts '✅ DRY RUN COMPLETE!'
535-
puts ''
536-
puts 'Review the commands above to see what would be executed.'
537-
puts ''
538-
puts 'To actually create the demo, run:'
539-
puts " bin/new-demo #{@demo_name}"
540-
else
541-
puts '🎉 DEMO CREATED SUCCESSFULLY!'
542-
puts ''
543-
puts " Location: #{@demo_dir}"
544-
puts " Created: #{@creation_start_time.strftime('%Y-%m-%d %H:%M:%S')}"
545-
puts ''
546-
puts '📋 Available Commands:'
547-
puts ''
548-
puts ' Start development server:'
549-
puts " $ cd #{@demo_dir} && bin/dev"
550-
puts ''
551-
puts ' Run E2E tests:'
552-
puts " $ cd #{@demo_dir} && npx playwright test"
553-
puts ''
554-
puts ' Run linting:'
555-
puts " $ cd #{@demo_dir} && bundle exec rubocop"
556-
puts ''
557-
puts '📚 Development Modes:'
558-
puts ' • bin/dev - HMR (Hot Module Replacement)'
559-
puts ' • bin/dev static - Static assets mode'
560-
puts ' • bin/dev prod - Production-like mode'
561-
puts ''
562-
puts '🔗 Useful URLs (when server is running):'
563-
puts ' • App: http://localhost:3000'
564-
puts ' • Hello World: http://localhost:3000/hello_world'
565-
puts ''
566-
puts "📝 Metadata: #{@demo_dir}/.demo-metadata.yml"
567-
puts ''
568-
end
550+
@dry_run ? print_dry_run_completion : print_success_completion
569551
puts '=' * 80
570552
puts ''
571553
end
554+
555+
def print_dry_run_completion
556+
puts '✅ DRY RUN COMPLETE!'
557+
puts ''
558+
puts 'Review the commands above to see what would be executed.'
559+
puts ''
560+
puts 'To actually create the demo, run:'
561+
puts " bin/new-demo #{@demo_name}"
562+
end
563+
564+
def print_success_completion
565+
puts '🎉 DEMO CREATED SUCCESSFULLY!'
566+
puts ''
567+
print_demo_info
568+
puts ''
569+
print_available_commands
570+
puts ''
571+
print_development_modes
572+
puts ''
573+
print_useful_urls
574+
puts ''
575+
puts "📝 Metadata: #{@demo_dir}/.demo-metadata.yml"
576+
puts ''
577+
end
578+
579+
def print_demo_info
580+
puts " Location: #{@demo_dir}"
581+
puts " Created: #{@creation_start_time.strftime('%Y-%m-%d %H:%M:%S')}"
582+
end
583+
584+
def print_available_commands
585+
puts '📋 Available Commands:'
586+
puts ''
587+
puts ' Start development server:'
588+
puts " $ cd #{@demo_dir} && bin/dev"
589+
puts ''
590+
puts ' Run E2E tests:'
591+
puts " $ cd #{@demo_dir} && npx playwright test"
592+
puts ''
593+
puts ' Run linting:'
594+
puts " $ cd #{@demo_dir} && bundle exec rubocop"
595+
end
596+
597+
def print_development_modes
598+
puts '📚 Development Modes:'
599+
puts ' • bin/dev - HMR (Hot Module Replacement)'
600+
puts ' • bin/dev static - Static assets mode'
601+
puts ' • bin/dev prod - Production-like mode'
602+
end
603+
604+
def print_useful_urls
605+
puts '🔗 Useful URLs (when server is running):'
606+
puts ' • App: http://localhost:3000'
607+
puts ' • Hello World: http://localhost:3000/hello_world'
608+
end
572609
end
573610
# rubocop:enable Metrics/ClassLength
574611
end

packages/shakacode_demo_common/config/rubocop.yml

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
# Based on Rails Omakase with adjustments for React on Rails
33

44
require:
5-
- rubocop-rails
65
- rubocop-performance
76

87
AllCops:
@@ -58,18 +57,6 @@ Metrics/BlockLength:
5857
Metrics/ClassLength:
5958
Max: 200
6059

61-
# Rails specific
62-
Rails/ApplicationRecord:
63-
Enabled: true
64-
65-
Rails/I18nLocaleTexts:
66-
Enabled: false
67-
6860
# Performance
6961
Performance/RedundantMerge:
7062
Enabled: true
71-
72-
# React on Rails specific patterns
73-
Rails/OutputSafety:
74-
Exclude:
75-
- 'app/helpers/react_on_rails_helper.rb'

packages/shakacode_demo_common/lib/generators/shakacode_demo_common/install/install_generator.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,15 @@ def add_to_gitignore
116116

117117
def install_cypress_on_rails_with_playwright
118118
say 'Installing cypress-on-rails with Playwright framework'
119-
run 'bin/rails generate cypress_on_rails:install --framework playwright --install_folder e2e'
119+
success = run 'bin/rails generate cypress_on_rails:install --framework playwright --install_folder e2e'
120+
121+
unless success
122+
say 'Failed to install cypress-on-rails generator', :red
123+
command = 'bin/rails generate cypress_on_rails:install --framework playwright --install_folder e2e'
124+
say "You may need to run: #{command}", :yellow
125+
end
126+
127+
success
120128
end
121129

122130
def create_playwright_test

0 commit comments

Comments
 (0)