react_on_rails 16.2.0.beta.20 → 16.2.0.test.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ef70b805581df2434eb25a94d7966bff1054bef5a5b64fa451f79bd8e064dc44
4
- data.tar.gz: d35563edad7c924906b5ba1f9c4abe4c2f79aa33543403b07e1b6e7c5dc51610
3
+ metadata.gz: d23e199f7597e88d219d9541c30d304328c182c98dc30bbdc35b9ec0fb1b5f73
4
+ data.tar.gz: fb3601578def2b46a71d6cfd52e96e2eec8a6c686ae27fca49baaee87801c9a4
5
5
  SHA512:
6
- metadata.gz: 1c59b37bfdcde488f7d6787cd5e7dc237f8e8f8ccd82f63adf9c6ca03f0cf18e17f8c4fa0ebe0540f5257b8c7b54d78ba812de36862f18eddef0b53491a5ec4b
7
- data.tar.gz: 1162217cf4ea3c525c8dc78b2c1913d62770d0b060bde898556ca802206e338c15328fa3597b2e0632783909aadb35d59fafa7abd3fd8e9823150f9adb2dcfc7
6
+ metadata.gz: 8d7d7e86dd5c0eca61463ed386d644defadf16cce0c249d47d2928b1fa53d606c77a2192122ba88797c39dfa636a1d8016ebe0e4e5de13d4e7be32daafb48d6c
7
+ data.tar.gz: 1a9e4e568f253f58bbea1f5e379bce832b6c3dec2b6e9719ec8e76e852eaf9669744b1c3cb146d5ba99f4b6738a0c5dd503a3a747b64aa9c3278f5a9fe2d2ab7
data/.rubocop.yml CHANGED
@@ -1,16 +1,36 @@
1
- # Inherits from root config
2
- inherit_from: ../.rubocop.yml
3
-
4
- # Merge Exclude arrays with parent instead of replacing them
5
- inherit_mode:
6
- merge:
7
- - Exclude
1
+ # This is the configuration used to check the rubocop source code.
2
+ # Check out: https://github.com/bbatsov/rubocop
3
+ require:
4
+ - rubocop-performance
5
+ - rubocop-rspec
8
6
 
9
7
  AllCops:
8
+ NewCops: enable
9
+ DisplayCopNames: true
10
+ TargetRubyVersion: 3.0.0
10
11
  SuggestExtensions: false
11
12
 
13
+ Include:
14
+ - '**/Rakefile'
15
+ - '**/config.ru'
16
+ - 'Gemfile'
17
+ - '**/*.rb'
18
+ - '**/*.rake'
19
+
12
20
  Exclude:
21
+ - '**/*.js'
22
+ - '**/node_modules/**/*'
23
+ - '**/public/**/*'
24
+ - '**/tmp/**/*'
25
+ - 'coverage/**/*'
26
+ - 'gen-examples/examples/**/*'
27
+ - 'node_modules/**/*'
28
+ - '../react_on_rails_pro/**/*' # Exclude pro package (has its own linting)
13
29
  - 'spec/dummy/bin/*'
30
+ - 'spec/fixtures/**/*'
31
+ - 'spec/react_on_rails/dummy-for-generators/**/*'
32
+ - 'tmp/**/*'
33
+ - 'vendor/**/*'
14
34
 
15
35
  Naming/FileName:
16
36
  Exclude:
@@ -18,6 +38,24 @@ Naming/FileName:
18
38
  - '**/Rakefile'
19
39
  - '**/Steepfile'
20
40
 
41
+ Layout/LineLength:
42
+ Max: 120
43
+
44
+ Style/StringLiterals:
45
+ EnforcedStyle: double_quotes
46
+
47
+ Style/Documentation:
48
+ Enabled: false
49
+
50
+ Style/HashEachMethods:
51
+ Enabled: true
52
+
53
+ Style/HashTransformKeys:
54
+ Enabled: true
55
+
56
+ Style/HashTransformValues:
57
+ Enabled: true
58
+
21
59
  Lint/AssignmentInCondition:
22
60
  Exclude:
23
61
  - 'spec/dummy/bin/spring'
@@ -28,19 +66,33 @@ Lint/SuppressedException:
28
66
  - 'spec/dummy/bin/rake'
29
67
 
30
68
  Metrics/AbcSize:
69
+ Max: 28
31
70
  Exclude:
32
71
  - 'lib/generators/react_on_rails/install_generator.rb' # Generator setup methods require comprehensive error handling
33
72
 
73
+ Metrics/CyclomaticComplexity:
74
+ Max: 7
75
+
76
+ Metrics/PerceivedComplexity:
77
+ Max: 10
78
+
34
79
  Metrics/ClassLength:
80
+ Max: 150
35
81
  Exclude:
36
82
  - 'lib/generators/react_on_rails/base_generator.rb' # Generator complexity justified
37
83
  - 'lib/react_on_rails/dev/server_manager.rb' # Dev tool with comprehensive help system
38
84
 
85
+ Metrics/ParameterLists:
86
+ Max: 5
87
+ CountKeywordArgs: false
88
+
39
89
  Metrics/MethodLength:
90
+ Max: 41
40
91
  Exclude:
41
92
  - 'lib/generators/react_on_rails/install_generator.rb' # Generator setup methods require comprehensive error handling
42
93
 
43
94
  Metrics/ModuleLength:
95
+ Max: 180
44
96
  Exclude:
45
97
  - 'spec/react_on_rails/engine_spec.rb' # Comprehensive engine tests require many examples
46
98
 
@@ -55,6 +107,18 @@ RSpec/AnyInstance:
55
107
  - 'spec/react_on_rails/binstubs/dev_static_spec.rb'
56
108
  - 'spec/react_on_rails/dev/**/*_spec.rb' # Dev module tests require system mocking
57
109
 
110
+ RSpec/DescribeClass:
111
+ Enabled: false
112
+
113
+ RSpec/ExampleLength:
114
+ Enabled: false
115
+
116
+ RSpec/MessageSpies:
117
+ Enabled: false
118
+
119
+ RSpec/NestedGroups:
120
+ Max: 4
121
+
58
122
  RSpec/BeforeAfterAll:
59
123
  Exclude:
60
124
  - 'spec/react_on_rails/generators/dev_tests_generator_spec.rb'
@@ -63,10 +127,19 @@ RSpec/BeforeAfterAll:
63
127
  - 'spec/react_on_rails/binstubs/dev_static_spec.rb'
64
128
  - 'spec/react_on_rails/dev/**/*_spec.rb' # Dev module tests require global setup
65
129
 
130
+ RSpec/MessageChain:
131
+ Enabled: false
132
+
133
+ RSpec/MultipleExpectations:
134
+ Enabled: false
135
+
66
136
  RSpec/MultipleDescribes:
67
137
  Exclude:
68
138
  - 'spec/dummy/spec/system/integration_spec.rb'
69
139
 
140
+ RSpec/MultipleMemoizedHelpers:
141
+ Max: 12
142
+
70
143
  Style/GlobalVars:
71
144
  Exclude:
72
145
  - 'spec/dummy/config/environments/development.rb'
@@ -83,3 +156,4 @@ RSpec/InstanceVariable:
83
156
  RSpec/StubbedMock:
84
157
  Exclude:
85
158
  - 'spec/react_on_rails/dev/**/*_spec.rb' # Dev module tests use mixed stub/mock patterns
159
+
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- eval_gemfile File.expand_path("../Gemfile.shared_dev_dependencies", __dir__)
4
-
5
3
  gem "shakapacker", "9.4.0"
6
4
  gem "bootsnap", require: false
7
5
  gem "rails", "~> 7.1"
@@ -37,6 +35,9 @@ group :development, :test do
37
35
  gem "pry-rescue"
38
36
  gem "rbs", require: false
39
37
  gem "steep", require: false
38
+ gem "rubocop", "1.61.0", require: false
39
+ gem "rubocop-performance", "~>1.20.0", require: false
40
+ gem "rubocop-rspec", "~>2.26", require: false
40
41
  gem "spring", "~> 4.0"
41
42
  gem "lefthook", require: false
42
43
  # Added for Ruby 3.5+ compatibility to silence warnings
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- react_on_rails (16.2.0.beta.20)
4
+ react_on_rails (16.2.0.test.3)
5
5
  addressable
6
6
  connection_pool
7
7
  execjs (~> 2.5)
@@ -31,8 +31,7 @@ module ReactOnRails
31
31
 
32
32
  def add_test_related_gems_to_gemfile
33
33
  gem("rspec-rails", group: :test)
34
- # NOTE: chromedriver-helper was deprecated in 2019. Modern selenium-webdriver (4.x)
35
- # and GitHub Actions have built-in driver management, so no driver helper is needed.
34
+ gem("chromedriver-helper", group: :test)
36
35
  gem("coveralls", require: false)
37
36
  end
38
37
 
@@ -124,75 +124,4 @@ module GeneratorHelper
124
124
  true
125
125
  end
126
126
  end
127
-
128
- # Check if SWC is configured as the JavaScript transpiler in shakapacker.yml
129
- #
130
- # @return [Boolean] true if SWC is configured or should be used by default
131
- #
132
- # Detection logic:
133
- # 1. If shakapacker.yml exists and specifies javascript_transpiler: parse it
134
- # 2. For Shakapacker 9.3.0+, SWC is the default if not specified
135
- # 3. Returns true for fresh installations (SWC is recommended default)
136
- #
137
- # @note This method is used to determine whether to install SWC dependencies
138
- # (@swc/core, swc-loader) instead of Babel dependencies during generation.
139
- #
140
- # @note Caching: The result is memoized for the lifetime of the generator instance.
141
- # If shakapacker.yml changes during generator execution (unlikely), the cached
142
- # value will not update. This is acceptable since generators run quickly.
143
- def using_swc?
144
- return @using_swc if defined?(@using_swc)
145
-
146
- @using_swc = detect_swc_configuration
147
- end
148
-
149
- private
150
-
151
- def detect_swc_configuration
152
- shakapacker_yml_path = File.join(destination_root, "config/shakapacker.yml")
153
-
154
- if File.exist?(shakapacker_yml_path)
155
- config = parse_shakapacker_yml(shakapacker_yml_path)
156
- transpiler = config.dig("default", "javascript_transpiler")
157
-
158
- # Explicit configuration takes precedence
159
- return transpiler == "swc" if transpiler
160
-
161
- # For Shakapacker 9.3.0+, SWC is the default
162
- return shakapacker_version_9_3_or_higher?
163
- end
164
-
165
- # Fresh install: SWC is recommended default for Shakapacker 9.3.0+
166
- shakapacker_version_9_3_or_higher?
167
- end
168
-
169
- def parse_shakapacker_yml(path)
170
- require "yaml"
171
- # Use safe_load_file for security (defense-in-depth, even though this is user's own config)
172
- # permitted_classes: [Symbol] allows symbol keys which shakapacker.yml may use
173
- # aliases: true allows YAML anchors (&default, *default) commonly used in Rails configs
174
- YAML.safe_load_file(path, permitted_classes: [Symbol], aliases: true)
175
- rescue ArgumentError
176
- # Older Psych versions don't support all parameters - try without aliases
177
- begin
178
- YAML.safe_load_file(path, permitted_classes: [Symbol])
179
- rescue ArgumentError
180
- # Very old Psych - fall back to safe_load with File.read
181
- YAML.safe_load(File.read(path), permitted_classes: [Symbol]) # rubocop:disable Style/YAMLFileRead
182
- end
183
- rescue StandardError
184
- # If we can't parse the file, return empty config
185
- {}
186
- end
187
-
188
- # Check if Shakapacker 9.3.0 or higher is available
189
- # This version made SWC the default JavaScript transpiler
190
- def shakapacker_version_9_3_or_higher?
191
- return true unless defined?(ReactOnRails::PackerUtils)
192
-
193
- ReactOnRails::PackerUtils.shakapacker_version_requirement_met?("9.3.0")
194
- rescue StandardError
195
- # If we can't determine version, assume latest (which uses SWC)
196
- true
197
- end
198
127
  end
@@ -99,13 +99,6 @@ module ReactOnRails
99
99
  @types/react-dom
100
100
  ].freeze
101
101
 
102
- # SWC transpiler dependencies (for Shakapacker 9.3.0+ default transpiler)
103
- # SWC is ~20x faster than Babel and is the default for new Shakapacker installations
104
- SWC_DEPENDENCIES = %w[
105
- @swc/core
106
- swc-loader
107
- ].freeze
108
-
109
102
  private
110
103
 
111
104
  def setup_js_dependencies
@@ -125,8 +118,6 @@ module ReactOnRails
125
118
  add_css_dependencies
126
119
  # Rspack dependencies are only added when --rspack flag is used
127
120
  add_rspack_dependencies if respond_to?(:options) && options&.rspack?
128
- # SWC dependencies are only added when SWC is the configured transpiler
129
- add_swc_dependencies if using_swc?
130
121
  # Dev dependencies vary based on bundler choice
131
122
  add_dev_dependencies
132
123
  end
@@ -241,26 +232,6 @@ module ReactOnRails
241
232
  MSG
242
233
  end
243
234
 
244
- def add_swc_dependencies
245
- puts "Installing SWC transpiler dependencies (20x faster than Babel)..."
246
- return if add_packages(SWC_DEPENDENCIES, dev: true)
247
-
248
- GeneratorMessages.add_warning(<<~MSG.strip)
249
- ⚠️ Failed to add SWC dependencies.
250
-
251
- SWC is the default JavaScript transpiler for Shakapacker 9.3.0+.
252
- You can install them manually by running:
253
- npm install --save-dev #{SWC_DEPENDENCIES.join(' ')}
254
- MSG
255
- rescue StandardError => e
256
- GeneratorMessages.add_warning(<<~MSG.strip)
257
- ⚠️ Error adding SWC dependencies: #{e.message}
258
-
259
- You can install them manually by running:
260
- npm install --save-dev #{SWC_DEPENDENCIES.join(' ')}
261
- MSG
262
- end
263
-
264
235
  def add_typescript_dependencies
265
236
  puts "Installing TypeScript dependencies..."
266
237
  return if add_packages(TYPESCRIPT_DEPENDENCIES, dev: true)
@@ -61,6 +61,7 @@ class BundlerSwitcher
61
61
  puts "✅ Updated assets_bundler to '#{@target_bundler}'"
62
62
  end
63
63
 
64
+ # rubocop:disable Metrics/CyclomaticComplexity
64
65
  def update_dependencies
65
66
  puts "📦 Updating package.json dependencies..."
66
67
 
@@ -85,7 +86,9 @@ class BundlerSwitcher
85
86
  puts "✅ Removed #{@target_bundler == 'rspack' ? 'webpack' : 'rspack'} dependencies"
86
87
  File.write(package_json_path, JSON.pretty_generate(package_json))
87
88
  end
89
+ # rubocop:enable Metrics/CyclomaticComplexity
88
90
 
91
+ # rubocop:disable Metrics/CyclomaticComplexity
89
92
  def install_dependencies
90
93
  puts "📥 Installing #{@target_bundler} dependencies..."
91
94
 
@@ -120,6 +123,7 @@ class BundlerSwitcher
120
123
 
121
124
  puts "✅ Installed #{@target_bundler} dependencies"
122
125
  end
126
+ # rubocop:enable Metrics/CyclomaticComplexity
123
127
 
124
128
  def detect_package_manager
125
129
  return "yarn" if File.exist?("yarn.lock")
@@ -468,6 +468,7 @@ module ReactOnRails
468
468
  check_npm_wildcards
469
469
  end
470
470
 
471
+ # rubocop:disable Metrics/CyclomaticComplexity
471
472
  def check_gem_wildcards
472
473
  gemfile_path = ENV["BUNDLE_GEMFILE"] || "Gemfile"
473
474
  return unless File.exist?(gemfile_path)
@@ -489,7 +490,9 @@ module ReactOnRails
489
490
  # Ignore errors reading Gemfile
490
491
  end
491
492
  end
493
+ # rubocop:enable Metrics/CyclomaticComplexity
492
494
 
495
+ # rubocop:disable Metrics/CyclomaticComplexity
493
496
  def check_npm_wildcards
494
497
  return unless File.exist?("package.json")
495
498
 
@@ -511,6 +514,7 @@ module ReactOnRails
511
514
  # Ignore other errors
512
515
  end
513
516
  end
517
+ # rubocop:enable Metrics/CyclomaticComplexity
514
518
 
515
519
  def check_key_configuration_files
516
520
  files_to_check = {
@@ -534,6 +538,7 @@ module ReactOnRails
534
538
  check_server_rendering_engine
535
539
  end
536
540
 
541
+ # rubocop:disable Metrics/CyclomaticComplexity
537
542
  def check_layout_files
538
543
  layout_files = Dir.glob("app/views/layouts/**/*.erb")
539
544
  return if layout_files.empty?
@@ -560,6 +565,7 @@ module ReactOnRails
560
565
  end
561
566
  end
562
567
  end
568
+ # rubocop:enable Metrics/CyclomaticComplexity
563
569
 
564
570
  # rubocop:disable Metrics/CyclomaticComplexity
565
571
  def check_server_rendering_engine
@@ -597,6 +603,7 @@ module ReactOnRails
597
603
  end
598
604
  # rubocop:enable Metrics/CyclomaticComplexity
599
605
 
606
+ # rubocop:disable Metrics/CyclomaticComplexity
600
607
  def check_shakapacker_configuration_details
601
608
  return unless File.exist?("config/shakapacker.yml")
602
609
 
@@ -625,6 +632,7 @@ module ReactOnRails
625
632
  checker.add_warning(" ⚠️ Could not run 'rake shakapacker:info': #{e.message}")
626
633
  end
627
634
  end
635
+ # rubocop:enable Metrics/CyclomaticComplexity
628
636
 
629
637
  def check_react_on_rails_configuration_details
630
638
  check_react_on_rails_initializer
@@ -5,9 +5,7 @@ require "English"
5
5
  module ReactOnRails
6
6
  module GitUtils
7
7
  def self.uncommitted_changes?(message_handler, git_installed: true)
8
- # Skip check in CI environments - CI often makes temporary modifications
9
- # (e.g., script/convert for minimum version testing) before running generators
10
- return false if ENV["CI"] == "true" || ENV["COVERAGE"] == "true"
8
+ return false if ENV["COVERAGE"] == "true"
11
9
 
12
10
  status = `git status --porcelain`
13
11
  return false if git_installed && status&.empty?
@@ -9,10 +9,11 @@ module ReactOnRails
9
9
  class RubyEmbeddedJavaScript
10
10
  class << self
11
11
  def reset_pool
12
- @js_context_pool = ConnectionPool.new(
12
+ options = {
13
13
  size: ReactOnRails.configuration.server_renderer_pool_size,
14
14
  timeout: ReactOnRails.configuration.server_renderer_timeout
15
- ) { create_js_context }
15
+ }
16
+ @js_context_pool = ConnectionPool.new(options) { create_js_context }
16
17
  end
17
18
 
18
19
  def reset_pool_if_server_bundle_was_modified
@@ -49,6 +50,7 @@ module ReactOnRails
49
50
  # Note, js_code does not have to be based on React.
50
51
  # js_code MUST RETURN json stringify Object
51
52
  # Calling code will probably call 'html_safe' on return value before rendering to the view.
53
+ # rubocop:disable Metrics/CyclomaticComplexity
52
54
  def exec_server_render_js(js_code, render_options, js_evaluator = nil)
53
55
  js_evaluator ||= self
54
56
  if render_options.trace
@@ -85,6 +87,7 @@ module ReactOnRails
85
87
  # We need to parse each chunk and replay the console messages.
86
88
  result.transform { |chunk| parse_result_and_replay_console_messages(chunk, render_options) }
87
89
  end
90
+ # rubocop:enable Metrics/CyclomaticComplexity
88
91
 
89
92
  def trace_js_code_used(msg, js_code, file_name = "tmp/server-generated.js", force: false)
90
93
  return unless ReactOnRails.configuration.trace || force
@@ -203,7 +203,7 @@ module ReactOnRails
203
203
  add_warning("⚠️ Could not parse package.json")
204
204
  end
205
205
 
206
- def check_package_version_sync
206
+ def check_package_version_sync # rubocop:disable Metrics/CyclomaticComplexity
207
207
  return unless File.exist?("package.json")
208
208
 
209
209
  begin
@@ -540,6 +540,7 @@ module ReactOnRails
540
540
  MSG
541
541
  end
542
542
 
543
+ # rubocop:disable Metrics/CyclomaticComplexity
543
544
  def check_gemfile_version_patterns
544
545
  gemfile_path = ENV["BUNDLE_GEMFILE"] || "Gemfile"
545
546
  return unless File.exist?(gemfile_path)
@@ -570,7 +571,9 @@ module ReactOnRails
570
571
  # Ignore errors reading Gemfile
571
572
  end
572
573
  end
574
+ # rubocop:enable Metrics/CyclomaticComplexity
573
575
 
576
+ # rubocop:disable Metrics/CyclomaticComplexity
574
577
  def report_dependency_versions(package_json)
575
578
  all_deps = package_json["dependencies"]&.merge(package_json["devDependencies"] || {}) || {}
576
579
 
@@ -587,6 +590,7 @@ module ReactOnRails
587
590
  add_success("✅ React DOM #{react_dom_version}")
588
591
  end
589
592
  end
593
+ # rubocop:enable Metrics/CyclomaticComplexity
590
594
 
591
595
  def report_shakapacker_version
592
596
  return unless File.exist?("Gemfile.lock")
@@ -98,12 +98,9 @@ module ReactOnRails
98
98
  exitstatus: #{status.exitstatus}#{stdout_msg}#{stderr_msg}
99
99
  MSG
100
100
 
101
- # Use warn to ensure output is visible in CI logs (goes to stderr)
102
- # and flush immediately before calling exit!
103
- warn wrap_message(msg)
104
- warn ""
105
- warn default_troubleshooting_section
106
- $stderr.flush
101
+ puts wrap_message(msg)
102
+ puts ""
103
+ puts default_troubleshooting_section
107
104
 
108
105
  # Rspec catches exit without! in the exit callbacks
109
106
  exit!(1)
@@ -470,6 +467,7 @@ module ReactOnRails
470
467
  #
471
468
  # @example Absolute paths outside Rails.root (edge case)
472
469
  # normalize_to_relative_path("/other/path/bundles") # => "/other/path/bundles"
470
+ # rubocop:disable Metrics/CyclomaticComplexity
473
471
  def self.normalize_to_relative_path(path)
474
472
  return nil if path.nil?
475
473
 
@@ -497,6 +495,7 @@ module ReactOnRails
497
495
  path_str
498
496
  end
499
497
  end
498
+ # rubocop:enable Metrics/CyclomaticComplexity
500
499
 
501
500
  def self.default_troubleshooting_section
502
501
  <<~DEFAULT
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ReactOnRails
4
- VERSION = "16.2.0.beta.20"
4
+ VERSION = "16.2.0.test.3"
5
5
  end
@@ -338,6 +338,7 @@ module ReactOnRails
338
338
  private
339
339
 
340
340
  # Resolve version from lockfiles if available, otherwise use package.json version
341
+ # rubocop:disable Metrics/CyclomaticComplexity
341
342
  def resolve_version(package_json_version, package_name)
342
343
  # If package.json specifies a local path or URL, don't try to resolve from lockfiles
343
344
  # Lockfiles may contain placeholder versions like "0.0.0" for local links
@@ -358,6 +359,7 @@ module ReactOnRails
358
359
  # Fall back to package.json version
359
360
  package_json_version
360
361
  end
362
+ # rubocop:enable Metrics/CyclomaticComplexity
361
363
 
362
364
  # Check if a version string represents a local path or URL
363
365
  def local_path_or_url_version?(version)
@@ -14,49 +14,12 @@ module ReactOnRails
14
14
  @all ||= { shakapacker_examples: [] }
15
15
  end
16
16
 
17
- # Supported React versions for compatibility testing
18
- # Keys are major version strings, values are specific version to pin to (nil = latest)
19
- REACT_VERSIONS = {
20
- "16" => "16.14.0",
21
- "17" => "17.0.2",
22
- "18" => "18.0.0",
23
- "19" => nil # nil means use latest (default)
24
- }.freeze
25
-
26
- # Supported React major versions (we test with latest patch of each)
27
- MINIMUM_SUPPORTED_REACT_MAJOR_VERSION = "16"
28
- LATEST_REACT_MAJOR_VERSION = "19"
29
-
30
- # Minimum Shakapacker version for compatibility testing
31
- MINIMUM_SHAKAPACKER_VERSION = "8.2.0"
32
-
33
- attr_reader :packer_type, :name, :generator_options, :react_version
34
-
35
- # Returns true if this example uses a pinned (non-latest) React version
36
- def pinned_react_version?
37
- !react_version.nil?
38
- end
39
-
40
- # Returns the actual React version string to use
41
- def react_version_string
42
- return nil unless react_version
43
-
44
- REACT_VERSIONS[react_version.to_s] || react_version
45
- end
17
+ attr_reader :packer_type, :name, :generator_options
46
18
 
47
- def initialize(packer_type: nil, name: nil, generator_options: nil, react_version: nil)
19
+ def initialize(packer_type: nil, name: nil, generator_options: nil)
48
20
  @packer_type = packer_type
49
21
  @name = name
50
22
  @generator_options = generator_options
51
- @react_version = react_version
52
-
53
- # Validate react_version is a known version to catch configuration errors early
54
- if @react_version && !REACT_VERSIONS.key?(@react_version.to_s)
55
- valid_versions = REACT_VERSIONS.keys.join(", ")
56
- raise ArgumentError, "Invalid react_version '#{@react_version}' for example '#{name}'. " \
57
- "Valid versions: #{valid_versions}"
58
- end
59
-
60
23
  self.class.all[packer_type.to_sym] << self
61
24
  end
62
25
 
@@ -1,23 +1,4 @@
1
- # Example Type Configuration for React on Rails Generator Tests
2
- #
3
- # CI Test Coverage:
4
- # -----------------
5
- # - Latest CI (all PRs): Runs shakapacker_examples_latest (React 19, Shakapacker 9.x)
6
- # Examples: basic, basic-server-rendering, redux, redux-server-rendering
7
- #
8
- # - Pinned CI (master): Runs shakapacker_examples_pinned (React 16, 17, 18 with Shakapacker 8.2.0)
9
- # Examples: basic-react16, basic-server-rendering-react16,
10
- # basic-react17, basic-server-rendering-react17,
11
- # basic-react18, basic-server-rendering-react18
12
- #
13
- # Terminology:
14
- # - "Latest" = Current React version (19) with latest Shakapacker (9.x)
15
- # - "Pinned" = Specific older React versions (16, 17, 18) for backward compatibility testing
16
- #
17
- # Note: We support React 16+ but test with latest patch of each major version.
18
-
19
1
  example_type_data:
20
- # Latest versions (React 19, Shakapacker 9.x)
21
2
  - name: basic
22
3
  generator_options: ''
23
4
  - name: basic-server-rendering
@@ -26,27 +7,3 @@ example_type_data:
26
7
  generator_options: --redux
27
8
  - name: redux-server-rendering
28
9
  generator_options: --redux --example-server-rendering
29
-
30
- # React 18 compatibility tests (uses Root API introduced in React 18)
31
- - name: basic-react18
32
- generator_options: ''
33
- react_version: '18'
34
- - name: basic-server-rendering-react18
35
- generator_options: --example-server-rendering
36
- react_version: '18'
37
-
38
- # React 17 compatibility tests (legacy render/hydrate API)
39
- - name: basic-react17
40
- generator_options: ''
41
- react_version: '17'
42
- - name: basic-server-rendering-react17
43
- generator_options: --example-server-rendering
44
- react_version: '17'
45
-
46
- # React 16 compatibility tests (oldest supported legacy API)
47
- - name: basic-react16
48
- generator_options: ''
49
- react_version: '16'
50
- - name: basic-server-rendering-react16
51
- generator_options: --example-server-rendering
52
- react_version: '16'
@@ -82,10 +82,7 @@ namespace :run_rspec do
82
82
  puts "Creating #{example_type.rspec_task_name} task"
83
83
  desc "Runs RSpec for #{example_type.name_pretty} only"
84
84
  task example_type.rspec_task_name_short => example_type.gen_task_name do
85
- # Use unbundled mode for pinned React version examples to ensure the example app's
86
- # Gemfile and gem versions are used, not the parent workspace's bundle
87
- run_tests_in(File.join(examples_dir, example_type.name),
88
- unbundled: example_type.pinned_react_version?)
85
+ run_tests_in(File.join(examples_dir, example_type.name)) # have to use relative path
89
86
  end
90
87
  end
91
88
 
@@ -94,52 +91,6 @@ namespace :run_rspec do
94
91
  ExampleType.all[:shakapacker_examples].each { |example_type| Rake::Task[example_type.rspec_task_name].invoke }
95
92
  end
96
93
 
97
- # Helper methods for filtering examples by React version
98
- def latest_examples
99
- ExampleType.all[:shakapacker_examples].reject(&:pinned_react_version?)
100
- end
101
-
102
- def react18_examples
103
- ExampleType.all[:shakapacker_examples].select { |e| e.react_version == "18" }
104
- end
105
-
106
- def react17_examples
107
- ExampleType.all[:shakapacker_examples].select { |e| e.react_version == "17" }
108
- end
109
-
110
- def react16_examples
111
- ExampleType.all[:shakapacker_examples].select { |e| e.react_version == "16" }
112
- end
113
-
114
- def pinned_version_examples
115
- ExampleType.all[:shakapacker_examples].select(&:pinned_react_version?)
116
- end
117
-
118
- desc "Runs Rspec for latest version example apps only (React 19, Shakapacker 9.x)"
119
- task shakapacker_examples_latest: latest_examples.map(&:gen_task_name) do
120
- latest_examples.each { |example_type| Rake::Task[example_type.rspec_task_name].invoke }
121
- end
122
-
123
- desc "Runs Rspec for React 18 example apps only (Shakapacker 8.2.0)"
124
- task shakapacker_examples_react18: react18_examples.map(&:gen_task_name) do
125
- react18_examples.each { |example_type| Rake::Task[example_type.rspec_task_name].invoke }
126
- end
127
-
128
- desc "Runs Rspec for React 17 example apps only (legacy render API)"
129
- task shakapacker_examples_react17: react17_examples.map(&:gen_task_name) do
130
- react17_examples.each { |example_type| Rake::Task[example_type.rspec_task_name].invoke }
131
- end
132
-
133
- desc "Runs Rspec for React 16 example apps only (oldest supported legacy API)"
134
- task shakapacker_examples_react16: react16_examples.map(&:gen_task_name) do
135
- react16_examples.each { |example_type| Rake::Task[example_type.rspec_task_name].invoke }
136
- end
137
-
138
- desc "Runs Rspec for all pinned version example apps (React 16, 17, and 18)"
139
- task shakapacker_examples_pinned: pinned_version_examples.map(&:gen_task_name) do
140
- pinned_version_examples.each { |example_type| Rake::Task[example_type.rspec_task_name].invoke }
141
- end
142
-
143
94
  Coveralls::RakeTask.new if ENV["USE_COVERALLS"] == "TRUE"
144
95
 
145
96
  desc "run all tests no examples"
@@ -188,23 +139,11 @@ end
188
139
  # If string is passed and it's not absolute, it's converted relative to root of the gem.
189
140
  # TEST_ENV_COMMAND_NAME is used to make SimpleCov.command_name unique in order to
190
141
  # prevent a name collision. Defaults to the given directory's name.
191
- # Options:
192
- # :command_name - name for SimpleCov (default: dir basename)
193
- # :rspec_args - additional rspec arguments (default: "")
194
- # :env_vars - additional environment variables (default: "")
195
- # :unbundled - run with unbundled_sh_in_dir for Bundler isolation (default: false)
196
- # This is required for pinned version examples because they have different
197
- # gem versions (e.g., Shakapacker 8.2.0) pinned in their Gemfile than the
198
- # parent workspace (Shakapacker 9.x). Without bundle isolation, Bundler
199
- # would inherit the parent's gem resolution and use the wrong versions.
200
- # Latest version examples don't need this because they use the same versions
201
- # as the parent workspace.
202
142
  def run_tests_in(dir, options = {})
203
143
  path = calc_path(dir)
204
144
 
205
145
  command_name = options.fetch(:command_name, path.basename)
206
146
  rspec_args = options.fetch(:rspec_args, "")
207
- unbundled = options.fetch(:unbundled, false)
208
147
 
209
148
  # Build environment variables as an array for proper spacing
210
149
  env_tokens = []
@@ -213,11 +152,5 @@ def run_tests_in(dir, options = {})
213
152
  env_tokens << "COVERAGE=true" if ENV["USE_COVERALLS"]
214
153
 
215
154
  env_vars = env_tokens.join(" ")
216
- command = "#{env_vars} bundle exec rspec #{rspec_args}"
217
-
218
- if unbundled
219
- unbundled_sh_in_dir(path.realpath, command)
220
- else
221
- sh_in_dir(path.realpath, command)
222
- end
155
+ sh_in_dir(path.realpath, "#{env_vars} bundle exec rspec #{rspec_args}")
223
156
  end
@@ -8,7 +8,6 @@
8
8
  require "yaml"
9
9
  require "rails/version"
10
10
  require "pathname"
11
- require "json"
12
11
 
13
12
  require_relative "example_type"
14
13
  require_relative "task_helpers"
@@ -16,89 +15,8 @@ require_relative "task_helpers"
16
15
  namespace :shakapacker_examples do # rubocop:disable Metrics/BlockLength
17
16
  include ReactOnRails::TaskHelpers
18
17
 
19
- # Updates React-related dependencies to a specific version
20
- def update_react_dependencies(deps, react_version)
21
- return unless deps
22
-
23
- deps["react"] = react_version
24
- deps["react-dom"] = react_version
25
- end
26
-
27
- # Updates Shakapacker to minimum supported version in either dependencies or devDependencies
28
- def update_shakapacker_dependency(deps, dev_deps)
29
- if dev_deps&.key?("shakapacker")
30
- dev_deps["shakapacker"] = ExampleType::MINIMUM_SHAKAPACKER_VERSION
31
- elsif deps&.key?("shakapacker")
32
- deps["shakapacker"] = ExampleType::MINIMUM_SHAKAPACKER_VERSION
33
- end
34
- end
35
-
36
- # Updates dependencies in package.json to use specific React version
37
- def update_package_json_for_react_version(package_json_path, react_version)
38
- return unless File.exist?(package_json_path)
39
-
40
- begin
41
- package_json = JSON.parse(File.read(package_json_path))
42
- rescue JSON::ParserError => e
43
- puts " ERROR: Failed to parse #{package_json_path}: #{e.message}"
44
- raise
45
- end
46
-
47
- deps = package_json["dependencies"]
48
- dev_deps = package_json["devDependencies"]
49
-
50
- update_react_dependencies(deps, react_version)
51
- # Shakapacker 8.2.0 requires webpack-assets-manifest ^5.x (v6.x uses ESM and breaks)
52
- # Always add this explicitly since the transitive dependency from shakapacker may be v6.x
53
- dev_deps["webpack-assets-manifest"] = "^5.0.6" if dev_deps
54
- # Shakapacker 8.2.0 requires babel-loader to be explicitly installed as a devDependency
55
- # (in 9.x this requirement was relaxed or the package structure changed)
56
- dev_deps["babel-loader"] = "^9.1.3" if dev_deps
57
- # @babel/plugin-transform-runtime is required by the default babel config but not
58
- # automatically included as a dependency in older Shakapacker versions
59
- dev_deps["@babel/plugin-transform-runtime"] = "^7.24.0" if dev_deps
60
- update_shakapacker_dependency(deps, dev_deps)
61
-
62
- # Add npm overrides to force specific React version, preventing yalc-linked
63
- # react-on-rails from pulling in React 19 as a transitive dependency
64
- package_json["overrides"] = {
65
- "react" => react_version,
66
- "react-dom" => react_version
67
- }
68
-
69
- File.write(package_json_path, "#{JSON.pretty_generate(package_json)}\n")
70
- end
71
-
72
- # Updates Gemfile to pin shakapacker to minimum version
73
- # (must match the npm package version exactly)
74
- def update_gemfile_versions(gemfile_path)
75
- return unless File.exist?(gemfile_path)
76
-
77
- gemfile_content = File.read(gemfile_path)
78
- # Replace any shakapacker gem line with exact version pin
79
- # Handle both single-line: gem 'shakapacker', '>= 8.2.0'
80
- # And multi-line declarations:
81
- # gem 'shakapacker',
82
- # '>= 8.2.0'
83
- gemfile_content = gemfile_content.gsub(
84
- /gem ['"]shakapacker['"][^\n]*(?:\n\s+[^g\n][^\n]*)*$/m,
85
- "gem 'shakapacker', '#{ExampleType::MINIMUM_SHAKAPACKER_VERSION}'"
86
- )
87
- File.write(gemfile_path, gemfile_content)
88
- end
89
-
90
- # Updates package.json and Gemfile to use specific React version for compatibility testing
91
- def apply_react_version(dir, react_version)
92
- update_package_json_for_react_version(File.join(dir, "package.json"), react_version)
93
- update_gemfile_versions(File.join(dir, "Gemfile"))
94
-
95
- puts " Updated package.json for compatibility testing:"
96
- puts " React: #{react_version}"
97
- puts " Shakapacker: #{ExampleType::MINIMUM_SHAKAPACKER_VERSION}"
98
- end
99
-
100
18
  # Define tasks for each example type
101
- ExampleType.all[:shakapacker_examples].each do |example_type| # rubocop:disable Metrics/BlockLength
19
+ ExampleType.all[:shakapacker_examples].each do |example_type|
102
20
  relative_gem_root = Pathname(gem_root).relative_path_from(Pathname(example_type.dir))
103
21
  # CLOBBER
104
22
  desc "Clobbers (deletes) #{example_type.name_pretty}"
@@ -128,31 +46,10 @@ namespace :shakapacker_examples do # rubocop:disable Metrics/BlockLength
128
46
  "REACT_ON_RAILS_SKIP_VALIDATION=true #{cmd}"
129
47
  end
130
48
  sh_in_dir(example_type.dir, generator_commands)
131
- # Re-run bundle install since dev_tests generator adds rspec-rails and coveralls to Gemfile
132
- bundle_install_in(example_type.dir)
133
-
134
- # Apply specific React version for compatibility testing examples
135
- if example_type.pinned_react_version?
136
- apply_react_version(example_type.dir, example_type.react_version_string)
137
- # Re-run bundle install since Gemfile was updated with pinned shakapacker version
138
- bundle_install_in(example_type.dir)
139
- # Run npm install BEFORE shakapacker:binstubs to ensure the npm shakapacker version
140
- # matches the gem version. The binstubs task loads the Rails environment which
141
- # validates version matching between gem and npm package.
142
- # Use --legacy-peer-deps to avoid peer dependency conflicts when yalc-linked
143
- # react-on-rails expects newer React versions
144
- sh_in_dir(example_type.dir, "npm install --legacy-peer-deps")
145
- # Regenerate Shakapacker binstubs after downgrading from 9.x to 8.2.x
146
- # The binstub format may differ between major versions
147
- unbundled_sh_in_dir(example_type.dir, "bundle exec rake shakapacker:binstubs")
148
- else
149
- sh_in_dir(example_type.dir, "npm install")
150
- end
49
+ sh_in_dir(example_type.dir, "npm install")
151
50
  # Generate the component packs after running the generator to ensure all
152
- # auto-bundled components have corresponding pack files created.
153
- # Use unbundled_sh_in_dir to ensure we're using the generated app's Gemfile
154
- # and gem versions, not the parent workspace's bundle context.
155
- unbundled_sh_in_dir(example_type.dir, "bundle exec rake react_on_rails:generate_packs")
51
+ # auto-bundled components have corresponding pack files created
52
+ sh_in_dir(example_type.dir, "bundle exec rake react_on_rails:generate_packs")
156
53
  end
157
54
  end
158
55
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: react_on_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 16.2.0.beta.20
4
+ version: 16.2.0.test.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Gordon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-12-13 00:00:00.000000000 Z
11
+ date: 2025-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable