mirror of
https://github.com/ether/etherpad-lite.git
synced 2026-07-18 00:57:55 +00:00
* fix: pad-wide view settings apply to the creator's own view (#7900) The pad creator is never "enforced upon themselves" (isPadSettingsEnforcedForMe is false whenever canEditPadSettings is true), so getEffectivePadOptions always merges their personal view overrides (cookies) on top of the pad-wide options. As a result, a creator who had at some point toggled e.g. their personal "Read content from right to left" carried a stale rtlIsTrue=false cookie that silently masked the pad-wide value they later set — toggling the pad-wide control (and then enforcing it) appeared to do nothing on the creator's own screen. Fix: when the creator changes a pad-wide view option, sync their personal pref to the chosen value so their own view adopts the pad-wide setting immediately. This deliberately does NOT change the precedence model — the creator can still override the setting afterwards via the "My view" controls, so the existing behaviour where a creator keeps personal overrides while enforcing settings for other users (pad_settings.spec.ts) is preserved. Adds a frontend test reproducing the stale-personal-cookie scenario. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: address Qodo review — clear cookies on the page's own context (#7900) browser.newContext()+clearCookies() cleared cookies on a throwaway context (not the page fixture under test) and leaked the context. Use page.context().clearCookies() so the regression test reliably starts without a stale rtlIsTrue pref. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9af77e7e3a
commit
9e8f9cb513
2 changed files with 70 additions and 0 deletions
|
|
@ -876,6 +876,14 @@ const pad = {
|
|||
options,
|
||||
changedBy: pad.myUserInfo.name || 'unnamed',
|
||||
});
|
||||
// The pad creator is never "enforced upon themselves", so their personal
|
||||
// view overrides (cookies) are always merged on top of the pad-wide value
|
||||
// in getEffectivePadOptions. A stale personal pref would therefore mask the
|
||||
// pad-wide value they just set, making the control appear to do nothing
|
||||
// (#7900). Sync the creator's personal pref to the value they chose so
|
||||
// their own view adopts it immediately. They can still override it
|
||||
// afterwards via the "My view" controls.
|
||||
pad.setMyViewOption(key, value);
|
||||
},
|
||||
changeViewOption: (key, value) => {
|
||||
const effectiveOptions = pad.getEffectivePadOptions();
|
||||
|
|
|
|||
62
src/tests/frontend-new/specs/rtl_pad_wide_enforce.spec.ts
Normal file
62
src/tests/frontend-new/specs/rtl_pad_wide_enforce.spec.ts
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import {expect, test} from "@playwright/test";
|
||||
import {goToNewPad} from "../helper/padHelper";
|
||||
import {showSettings} from "../helper/settingsHelper";
|
||||
|
||||
// Regression test for ether/etherpad#7900.
|
||||
//
|
||||
// The pad creator is never "enforced upon themselves" (they can always edit
|
||||
// pad settings), so their personal view overrides (cookies) are always merged
|
||||
// on top of the pad-wide options in getEffectivePadOptions. A creator who had
|
||||
// at some point toggled their personal "Read content from right to left"
|
||||
// carried a stale rtlIsTrue=false cookie that silently masked the pad-wide RTL
|
||||
// value they later set — the pad content stayed LTR and the pad-wide control
|
||||
// appeared to "do nothing".
|
||||
//
|
||||
// Fix: changePadViewOption syncs the creator's personal pref to the value they
|
||||
// chose, so their own view adopts the pad-wide setting immediately (while still
|
||||
// allowing them to override it afterwards via the "My view" controls).
|
||||
test.beforeEach(async ({page}) => {
|
||||
// Clear cookies on the context of the page under test (not a throwaway
|
||||
// context) so the test reliably starts without a stale rtlIsTrue pref.
|
||||
await page.context().clearCookies();
|
||||
await goToNewPad(page);
|
||||
});
|
||||
|
||||
test.describe('RTL pad-wide + enforce', function () {
|
||||
test('pad-wide RTL applies to the creator even with a stale personal setting', {tag: '@feature:rtl-toggle'}, async function ({page}) {
|
||||
const innerBody = page
|
||||
.frameLocator('iframe[name="ace_outer"]')
|
||||
.frameLocator('iframe[name="ace_inner"]')
|
||||
.locator('#innerdocbody');
|
||||
const computedDir = () => innerBody.evaluate((el) =>
|
||||
el.ownerDocument.defaultView!.getComputedStyle(el).direction);
|
||||
|
||||
await showSettings(page);
|
||||
|
||||
// The checkboxes are visually replaced by styled labels, so drive the UI
|
||||
// the way a user does — by clicking the labels.
|
||||
// The creator first toggles their PERSONAL RTL on, then off. This writes a
|
||||
// personal cookie pref rtlIsTrue=false that used to mask the pad-wide value.
|
||||
await page.locator('label[for="options-rtlcheck"]').click();
|
||||
await expect(page.locator('#options-rtlcheck')).toBeChecked();
|
||||
await expect.poll(computedDir).toBe('rtl');
|
||||
await page.locator('label[for="options-rtlcheck"]').click();
|
||||
await expect(page.locator('#options-rtlcheck')).not.toBeChecked();
|
||||
await expect.poll(computedDir).toBe('ltr');
|
||||
|
||||
// Pad-wide settings are visible because the new pad's first user is its
|
||||
// creator (canEditPadSettings). Setting pad-wide RTL must now flip the
|
||||
// creator's own content despite the stale personal cookie...
|
||||
await page.locator('label[for="padsettings-options-rtlcheck"]').click();
|
||||
await expect(page.locator('#padsettings-options-rtlcheck')).toBeChecked();
|
||||
await expect.poll(computedDir).toBe('rtl');
|
||||
await expect(innerBody).toHaveClass(/\brtl\b/);
|
||||
// ...and the personal control reflects the synced value.
|
||||
await expect(page.locator('#options-rtlcheck')).toBeChecked();
|
||||
|
||||
// Enforcing for other users keeps the creator's content RTL.
|
||||
await page.locator('label[for="padsettings-enforcecheck"]').click();
|
||||
await expect(page.locator('#padsettings-enforcecheck')).toBeChecked();
|
||||
await expect.poll(computedDir).toBe('rtl');
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue