test: regression tests for Settings CJS compat (#7543)#7551
Merged
JohnMcLear merged 1 commit intodevelopfrom Apr 19, 2026
Merged
test: regression tests for Settings CJS compat (#7543)#7551JohnMcLear merged 1 commit intodevelopfrom
JohnMcLear merged 1 commit intodevelopfrom
Conversation
#7421 fixed the ESM/CJS interop bug where plugins using require('ep_etherpad-lite/node/utils/Settings') got an object whose .toolbar (and every other top-level field) was undefined, crashing ep_font_color/ep_font_size/ep_plugin_helpers with "Cannot read properties of undefined (reading 'indexOf')" during pad.html rendering. That fix landed without a regression test. Pin the contract: top-level settings fields must be reachable via a CJS require(), the toolbar must keep its {left, right, timeslider} shape, and setters on the shim must propagate to the underlying settings object so reloadSettings() is visible to plugins. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Review Summary by QodoAdd regression tests for Settings CJS compatibility (#7543)
WalkthroughsDescription• Adds regression tests for Settings CJS compatibility • Verifies top-level fields accessible via require() without .default wrapper • Tests toolbar structure with left/right/timeslider arrays • Validates setter propagation for reloadSettings() visibility Diagramflowchart LR
A["Settings CJS Compat Bug #7543"] --> B["Require returns undefined fields"]
B --> C["Plugins crash on toolbar.indexOf"]
D["CJS Compat Shim #7421"] --> E["Re-expose fields via accessors"]
E --> F["Tests verify contract"]
F --> G["Top-level fields accessible"]
F --> H["Toolbar structure preserved"]
F --> I["Setters propagate changes"]
File Changes1. src/tests/backend/specs/settings.ts
|
Code Review by Qodo
1. Protocol-specific GitHub URL
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What happened:
Someone installed Etherpad, added the ep_font_color plugin, and the pad page crashed with Cannot read
properties of undefined (reading 'indexOf').
Why:
Etherpad used to be written in plain JavaScript. We rewrote the Settings file in TypeScript and made it
"modern" — saying export default settings.
Plugins like ep_font_color still do the old thing: require('…/Settings').toolbar. Under the new modern
rules, that now gives you { default: { toolbar: … } } instead of the old flat { toolbar: … }. So
settings.toolbar is undefined, and then .indexOf(…) blows up.
The fix (already on develop, not in v2.6.1):
PR #7421 added a small shim at the bottom of Settings.ts that puts every top-level field (like toolbar,
skinName) back directly on module.exports. Plugins can read .toolbar again without knowing anything
changed.
What I did today:
The original fix shipped with no test. If someone refactors that shim in six months, nobody would notice
until plugins crash again. I opened PR #7551 with 4 tests that lock in the contract:
For the user stuck on v2.6.1: fix isn't in any release yet — run develop, or uninstall
ep_font_color/ep_font_size/ep_plugin_helpers, until the next tag.
Summary
Pins the contract that #7421 restored: plugins using
require('ep_etherpad-lite/node/utils/Settings')must be able to readtop-level fields (
.toolbar,.skinName,.padOptions, …) directly,without fishing through a
.defaultwrapper.The original bug (#7543) manifested as:
because
settings.toolbarcame backundefinedunder tsx's ESM/CJSinterop. #7421 added a CJS compat shim that re-exposes each top-level
field on
module.exportsvia accessor properties, but shipped withouta regression test. This PR adds four focused tests:
exposes top-level fields directly on require() result— covers theexact failure mode of Crash after fresh install and addition of plugins. #7543.
toolbar has the shape plugins index into (left/right/timeslider)—covers
JSON.stringify(toolbar).indexOf(...)in ep_font_color.does not hide the real value under a .default wrapper— guardsagainst a future refactor that forgets the shim.
setters propagate so reloadSettings() changes are visible to plugins—covers the setter path added by fix: add setters to CJS compatibility layer in Settings #7481.
No production code changes — tests only. Fix is already on develop.
Test plan
Linux without pluginsandLinux with Pluginsboth green.npx mocha --import=tsx --timeout 120000 tests/backend/specs/settings.ts -g "CJS compatibility".src/node/utils/Settings.tsortoolbar.ts.Closes #7543.
🤖 Generated with Claude Code