Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby "3.3.4"

gem "react_on_rails", "16.1.1"
gem "shakapacker", "8.2.0"
gem "shakapacker", "9.0.0.beta.7"

# Bundle edge Rails instead: gem "rails", github: "rails/rails"
gem "listen"
Expand Down
4 changes: 2 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ GEM
websocket (~> 1.0)
semantic_range (3.1.0)
sexp_processor (4.17.1)
shakapacker (8.2.0)
shakapacker (9.0.0.beta.7)
activesupport (>= 5.2)
package_json
rack-proxy (>= 0.6.1)
Expand Down Expand Up @@ -499,7 +499,7 @@ DEPENDENCIES
scss_lint
sdoc
selenium-webdriver (~> 4)
shakapacker (= 8.2.0)
shakapacker (= 9.0.0.beta.7)
spring
spring-commands-rspec
stimulus-rails (~> 1.3)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ class CommentForm extends BaseComponent {
}

formHorizontal() {
const { formatMessage } = this.props.intl;
const { intl } = this.props;
const { formatMessage } = intl;
Copy link

Copilot AI Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential runtime error if intl prop is undefined during SSR. Consider adding a null check: const { formatMessage } = intl || {}; or guard against undefined intl.

Suggested change
const { formatMessage } = intl;
const { formatMessage } = intl || { formatMessage: (msg) => (msg && msg.defaultMessage) || '' };

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential null reference error if intl is undefined during SSR. Add a null check: const { formatMessage } = intl || {}; or provide a fallback to prevent runtime errors.

Copilot uses AI. Check for mistakes.
return (
<div>
<hr />
Expand Down Expand Up @@ -156,7 +157,8 @@ class CommentForm extends BaseComponent {
}

formStacked() {
const { formatMessage } = this.props.intl;
const { intl } = this.props;
const { formatMessage } = intl;
Copy link

Copilot AI Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential runtime error if intl prop is undefined during SSR. Consider adding a null check: const { formatMessage } = intl || {}; or guard against undefined intl.

Copilot uses AI. Check for mistakes.
return (
<div>
<hr />
Expand Down Expand Up @@ -211,7 +213,8 @@ class CommentForm extends BaseComponent {

// Head up! We have some CSS modules going on here with the className props below.
formInline() {
const { formatMessage } = this.props.intl;
const { intl } = this.props;
const { formatMessage } = intl;
Copy link

Copilot AI Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential runtime error if intl prop is undefined during SSR. Consider adding a null check: const { formatMessage } = intl || {}; or guard against undefined intl.

Copilot uses AI. Check for mistakes.
return (
<div>
<hr />
Expand Down Expand Up @@ -314,7 +317,8 @@ class CommentForm extends BaseComponent {
throw new Error(`Unknown form mode: ${this.state.formMode}.`);
}

const { formatMessage } = this.props.intl;
const { intl } = this.props;
const { formatMessage } = intl;
Copy link

Copilot AI Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential runtime error if intl prop is undefined during SSR. Consider adding a null check: const { formatMessage } = intl || {}; or guard against undefined intl.

Suggested change
const { formatMessage } = intl;
const { formatMessage } = intl || {};

Copilot uses AI. Check for mistakes.

// For animation with TransitionGroup
// https://reactcommunity.org/react-transition-group/transition-group
Expand Down Expand Up @@ -352,7 +356,6 @@ class CommentForm extends BaseComponent {
>
{formatMessage(defaultMessages.formInline)}
</button>
{}
</div>
{inputForm}
</div>
Expand Down
1 change: 1 addition & 0 deletions config/shakapacker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ default: &default
cache_path: tmp/shakapacker
webpack_compile_output: true
nested_entries: true
javascript_transpiler: babel

# Additional paths webpack should lookup modules
# ['app/assets', 'engine/foo/app/assets']
Expand Down
19 changes: 19 additions & 0 deletions config/webpack/commonWebpackConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,25 @@ if (sassLoaderIndex !== -1) {
}
}

// Fix css-loader configuration for CSS modules
// When namedExport is true, exportLocalsConvention must be camelCaseOnly or dashesOnly
const cssLoaderIndex = scssRule.use.findIndex((loader) => {
if (typeof loader === 'string') {
return loader.includes('css-loader');
}
return loader.loader && loader.loader.includes('css-loader');
});

if (cssLoaderIndex !== -1) {
const cssLoader = scssRule.use[cssLoaderIndex];
if (typeof cssLoader === 'object' && cssLoader.options && cssLoader.options.modules) {
// If namedExport is enabled, ensure exportLocalsConvention is properly set
if (cssLoader.options.modules.namedExport) {
cssLoader.options.modules.exportLocalsConvention = 'camelCaseOnly';
}
}
}

baseClientWebpackConfig.module.rules[scssConfigIndex].use.push(sassLoaderConfig);

// Copy the object using merge b/c the baseClientWebpackConfig and commonOptions are mutable globals
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
"sass": "^1.58.3",
"sass-loader": "^13.3.2",
"sass-resources-loader": "^2.2.5",
"shakapacker": "8.2.0",
"shakapacker": "9.0.0-beta.7",
"stimulus": "^3.0.1",
"style-loader": "^3.3.1",
"tailwindcss": "^3.3.3",
Expand Down
2 changes: 1 addition & 1 deletion spec/rails_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
# Ensure that if we are running js tests, we are using latest webpack assets
# This will use the defaults of :js and :server_rendering meta tags
ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config)
# Register the headless Chrome driver
# Register headless Chrome driver using centralized configuration
DriverRegistration.register_selenium_chrome_headless

# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
Expand Down
21 changes: 13 additions & 8 deletions spec/support/driver_registration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,22 @@ def self.register_selenium_firefox
end

def self.register_selenium_chrome_headless
return if @selenium_headless_registered
# Force re-register to ensure our configuration is used
Capybara.drivers.delete(:selenium_chrome_headless)

Capybara.register_driver :selenium_chrome_headless do |app|
capabilities = Selenium::WebDriver::Chrome::Options.new(
"goog:chromeOptions" => { args: %w[headless disable-gpu no-sandbox disable-dev-shm-usage] }
)
Capybara::Selenium::Driver.new app, browser: :chrome, options: capabilities
browser_options = ::Selenium::WebDriver::Chrome::Options.new
browser_options.args << "--headless"
browser_options.args << "--disable-gpu"
browser_options.args << "--no-sandbox"
browser_options.args << "--disable-dev-shm-usage"
browser_options.args << "--window-size=1920,1080"

Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options)
end
Capybara::Screenshot.register_driver(:selenium_chrome_headless) do |js_driver, path|
js_driver.browser.save_screenshot(path)

Capybara::Screenshot.register_driver(:selenium_chrome_headless) do |driver, path|
driver.browser.save_screenshot(path)
end
@selenium_headless_registered = true
end
end
11 changes: 6 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8263,13 +8263,14 @@ [email protected]:
resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==

shakapacker@8.2.0:
version "8.2.0"
resolved "https://registry.npmjs.org/shakapacker/-/shakapacker-8.2.0.tgz#c7bed87b8be2ae565cfe616f68552be545c77e14"
integrity sha512-Ct7BFqJVnKbxdqCzG+ja7Q6LPt/PlB7sSVBfG5jsAvmVCADM05cuoNwEgYNjFGKbDzHAxUqy5XgoI9Y030+JKQ==
shakapacker@9.0.0-beta.7:
version "9.0.0-beta.7"
resolved "https://registry.npmjs.org/shakapacker/-/shakapacker-9.0.0-beta.7.tgz#c00b9590b84f365bf0fd4e7b7efdd59104901a00"
integrity sha512-m4xGyTg9yy4ys+wz44jBdygsxwKDbARBlgYqsyirwowQKWZHqnyb+ucS9yz5cKQHUtHeDlJOhPHKhRsCwhJcDQ==
dependencies:
js-yaml "^4.1.0"
path-complete-extname "^1.0.0"
webpack-merge "^5.8.0"

shallow-clone@^3.0.0:
version "3.0.1"
Expand Down Expand Up @@ -9204,7 +9205,7 @@ webpack-dev-server@^4.11.1:
webpack-dev-middleware "^5.3.4"
ws "^8.13.0"

webpack-merge@5, webpack-merge@^5.7.3:
webpack-merge@5, webpack-merge@^5.7.3, webpack-merge@^5.8.0:
version "5.10.0"
resolved "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177"
integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==
Expand Down