Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
3 changes: 3 additions & 0 deletions src/BloomBrowserUI/bookEdit/topbar/editTopBarControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,9 @@ export const EditingControlButton: React.FunctionComponent<{
<BloomButton
enabled={props.enabled}
l10nKey={props.l10nKey}
// For the e2e tests (src/BloomE2E/helpers/workspace.ts), which must find the
// button by something other than its localized label.
data-testid={`edit-top-bar-${props.onClickAction}-button`}
onMouseDown={(e) => {
// Keep focus in the main editable browser; otherwise this button takes focus
// first and copy/cut/paste/undo may run against the wrong context.
Expand Down
28 changes: 28 additions & 0 deletions src/BloomE2E/AUTOMATION-DEBT.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ Format dialog, so the test drives it in the Format dialog (`helpers/fontChooser.
Settings route stays manual. `settings/setFontForLanguage` is not a way round it: like the other
settings endpoints it only records a pending change on the open dialog.

seen again 2026-09-08 (Test Case ID 364, `text-formatting-shortcuts.spec.ts`): the manual test undoes
with the Edit tab's Undo button and with Ctrl+Z. The button is in the React top bar now, so the test
clicks it (`helpers/workspace.ts clickUndoButton`, by a test id added for it). Ctrl+Z is still a
WinForms accelerator that the shell handles before the browser sees it, so no test can press it; the
test calls `undo`, the production path with only the key press missing, for that step. Fix
direction: an `e2e/` hook that runs the shell's own accelerator handling for a named key, so a test
can say "press Ctrl+Z" and have the shell answer as it does for a person.

## Native OS dialogs hang automation

File pickers, the Image Toolbox, and video capture open native windows Playwright
Expand Down Expand Up @@ -497,6 +505,26 @@ So: **to test the working tree, serve the dev server on 5173 and set
`BLOOM_E2E_VITE_PORT=5173`.** Fix direction: emit the port into those two pug files the way the
shell gets it, so `--vite-port` means what it says. (Found 2026-09-02.)

## The text color palette sometimes does not open on the first click

The formatting toolbar's Text Color button drops down a CKEditor panel of swatches. `attachToCkEditor`
in `bookEdit/js/bloomEditing.ts` hides every `.cke_panel` on every CKEditor `selectionCheck`, to stop
the palette from popping up on its own each time the toolbar shows (its comment says nobody knows
why it does). CKEditor checks the selection a moment after each mouseup, on a timer, so when that
check lands after the click has opened the panel, the panel is hidden again while the button still
shows as "on": the click looks as if it did nothing, and the next click closes the panel CKEditor
thinks is open rather than showing it. Seen 2026-09-08 (Test Case ID 364,
`text-formatting-shortcuts.spec.ts`): the second color pick of a run failed this way about one run in
two, the first never did. Worse, a swatch click delivered into a panel that closed at that moment
landed on the text beneath it and moved the selection, so the color went on half a word.
`helpers/textFormatting.ts pickTextColorFromToolbar` therefore waits out CKEditor's 200ms
selection-check throttle after the panel opens, clicks a swatch only in a panel that is still
showing, clicks the button again otherwise (which is what a person does), and fails if the
selection moved. Fix direction: find out why the panel reappears
on its own (CKEditor's floatpanel remembers `showBlockParams`, and Bloom's `display:none` bypasses
its `hide`, so its state and the DOM disagree from then on) and hide it through `panel.hide()`
instead, or only on `selectionChange` rather than on every check. A person can hit this too.

## Canvas element toolbar buttons are anonymous

The floating toolbar over a selected canvas element (`#canvas-element-context-controls`,
Expand Down
31 changes: 31 additions & 0 deletions src/BloomE2E/helpers/bookMaking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,37 @@ export async function typeInGroup(
await expect(box).toHaveText(text, { timeout: 15000 });
}

/**
* Type several paragraphs into one language's box of one translation group, the way a person does:
* the first as typeInGroup types it, then Enter and the next, and so on. The box ends up holding one
* <p> per paragraph, which is what a test of anything paragraph-shaped needs to start from.
*
* As with typeInGroup, nothing reaches the file until the book leaves this page — see goToPage.
*/
export async function typeParagraphsInGroup(
page: Page,
groupSelector: string,
languageTag: string,
paragraphs: string[],
): Promise<void> {
if (paragraphs.length === 0)
throw new Error("typeParagraphsInGroup needs at least one paragraph.");
await typeInGroup(page, groupSelector, languageTag, paragraphs[0]);
// typeInGroup leaves the caret at the end of what it typed, so each Enter starts a new paragraph
// after the last one. Enter is a real key press because CKEditor makes the paragraph from it.
for (const paragraph of paragraphs.slice(1)) {
await page.keyboard.press("Enter");
await page.keyboard.insertText(paragraph);
}
const box = editablePageFrame(page)
.locator(`${groupSelector} .bloom-editable[lang="${languageTag}"]`)
.first();
await expect(
box.locator(":scope > p"),
`The "${languageTag}" box of "${groupSelector}" did not end up with one paragraph per string typed.`,
).toHaveText(paragraphs, { timeout: 15000 });
}

/**
* The font one language's box of one translation group is shown in: the first family of its computed
* font-family, without quotes, e.g. "Andika". This is how a test checks that a font chosen in the
Expand Down
Loading