mirror of
https://github.com/ether/etherpad-lite.git
synced 2026-05-05 04:06:37 +02:00
#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>
This commit is contained in:
parent
e58dfa4752
commit
c4add0260d
@ -89,4 +89,62 @@ describe(__filename, function () {
|
||||
assert.deepEqual(settings!.ep_webrtc, {"enabled": true});
|
||||
})
|
||||
})
|
||||
|
||||
// Regression test for https://github.com/ether/etherpad/issues/7543.
|
||||
// Plugins (ep_font_color, ep_font_size, ep_plugin_helpers, …) consume
|
||||
// Settings via CommonJS require(), which under tsx/ESM interop would place
|
||||
// the default export under .default and leave top-level fields undefined.
|
||||
// That broke template rendering with:
|
||||
// TypeError: Cannot read properties of undefined (reading 'indexOf')
|
||||
// when plugins called settings.toolbar.left / etc.
|
||||
//
|
||||
// The CJS compat layer in Settings.ts re-exposes every top-level field on
|
||||
// module.exports via accessor properties, so require(...).<field> resolves
|
||||
// even though the source uses `export default`. This test asserts that
|
||||
// contract so a future refactor can't regress it silently.
|
||||
describe('CJS compatibility for plugin consumers', function () {
|
||||
it('exposes top-level fields directly on require() result', function () {
|
||||
const cjs = require('../../../node/utils/Settings');
|
||||
// The three fields most commonly read by first-party plugins.
|
||||
assert.notStrictEqual(cjs.toolbar, undefined,
|
||||
'settings.toolbar must be reachable via CJS require');
|
||||
assert.notStrictEqual(cjs.skinName, undefined,
|
||||
'settings.skinName must be reachable via CJS require');
|
||||
assert.notStrictEqual(cjs.padOptions, undefined,
|
||||
'settings.padOptions must be reachable via CJS require');
|
||||
});
|
||||
|
||||
it('toolbar has the shape plugins index into (left/right/timeslider)', function () {
|
||||
const cjs = require('../../../node/utils/Settings');
|
||||
// ep_font_color and friends JSON.stringify(settings.toolbar) then call
|
||||
// .indexOf on the result, so the object must be present and well-formed.
|
||||
assert.ok(cjs.toolbar && typeof cjs.toolbar === 'object');
|
||||
assert.ok(Array.isArray(cjs.toolbar.left));
|
||||
assert.ok(Array.isArray(cjs.toolbar.right));
|
||||
assert.ok(Array.isArray(cjs.toolbar.timeslider));
|
||||
});
|
||||
|
||||
it('does not hide the real value under a .default wrapper', function () {
|
||||
const cjs = require('../../../node/utils/Settings');
|
||||
// If export-default handling regresses, consumers end up seeing a
|
||||
// {default: {...}} wrapper and .toolbar on the wrapper is undefined.
|
||||
// Either shape is acceptable as long as .toolbar is directly present,
|
||||
// which is what the CJS compat shim guarantees.
|
||||
if (cjs.default != null && cjs.default.toolbar != null) {
|
||||
assert.strictEqual(cjs.toolbar, cjs.default.toolbar,
|
||||
'require().toolbar must be the same object as require().default.toolbar');
|
||||
}
|
||||
});
|
||||
|
||||
it('setters propagate so reloadSettings() changes are visible to plugins', function () {
|
||||
const cjs = require('../../../node/utils/Settings');
|
||||
const original = cjs.title;
|
||||
try {
|
||||
cjs.title = 'cjs-shim-test';
|
||||
assert.strictEqual(cjs.title, 'cjs-shim-test');
|
||||
} finally {
|
||||
cjs.title = original;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user