There is 1 comment.
 
 
XWiki Platform / cid:jira-generated-image-avatar-b077dbea-aaae-492e-9fcd-04a3d612e5bd XWIKI-24749 Open

ImageIT#editImage is flickering

 
View issue   ·   Add comment
 

1 comment

 
cid:jira-generated-image-avatar-2a520a08-5661-44fe-a2ce-fc0de9f36adb XWiki.org LLM Bot on 24/Sep/26 04:45
 

Daily CI-sweep: attempted flicker-stabilisation candidate — inconclusive, no PR opened

This issue was picked as today's one flicker-stabilisation candidate by the automated CI sweep. Summary of what was attempted and why it stopped short of a fix PR.

Root cause — verified

Confirmed by direct code inspection (matches this issue's reported org.openqa.selenium.NoSuchElementException on ".image-editor-modal" exactly):

  • ImageDialogEditModal() calls this(By.className("image-editor-modal")), which calls super(selector) before its own getDriver().waitUntilElementIsVisible(selector) runs.
  • BaseModal(By selector)'s constructor does this.container = getDriver().findElement(selector); — a single lookup with only the driver's short implicit wait, no polling.
  • So the very first lookup for this modal happens in BaseModal's constructor, invoked via super(selector), before ImageDialogEditModal's own polling wait ever gets a chance to run. If the blocknote React modal hasn't rendered yet at that instant, findElement throws the raw NoSuchElementException instead.

Candidate fix (identified, not applied/committed)

Test/page-object-only change, one call site, mirroring the existing pattern two methods below it in the same file (insertMacro() / editMacro(), which call .waitUntilReady()):

public ImageDialogEditModal editImage()
{
    clickButton("changeimage");
    getDriver().waitUntilElementIsVisible(By.className("image-editor-modal"));
    return new ImageDialogEditModal();
}

in BlockNoteToolBar.java (By is already imported). Does not touch BaseModal or ImageDialogEditModal, so the blast radius is limited to this one call site.

Measurement attempt — inconclusive

Ran the unfixed AllIT$NestedImageIT#editImage test 6× locally on the documented configuration (chrome / postgresql latest / tomcat 11-jdk25), using the repeat-run tooling in fresh mode (this configuration isn't compatible with the fast jetty_standalone reuse loop).

All 6 executions failed — but none with the signature this issue is about. Every one failed with a different, deterministic error:

org.openqa.selenium.TimeoutException: Expected condition failed: waiting for ... (tried for 10 seconds with 500 milliseconds interval)
	at org.xwiki.test.ui.XWikiWebDriver.waitUntilElementDisappears(XWikiWebDriver.java:402)
	at org.xwiki.wysiwyg.test.po.image.ImageDialogEditModal.<init>(ImageDialogEditModal.java:51)
	at org.xwiki.blocknote.test.po.BlockNoteToolBar.editImage(BlockNoteToolBar.java:117)

i.e. the modal's own getDriver().waitUntilElementDisappears(this.container, By.className("loading")) call (line 51) timing out — a different code path in the same constructor, downstream of the race this issue is about. Tracing it: the .loading class is only cleared once a same-origin AJAX call to XWiki.WYSIWYG.ImageEditorService (and the subsequent initImageStyleField() promise) resolves (see imageEditor.js's initialize()). On the single, resource-constrained machine these 6 repetitions ran on — Postgres + embedded Solr + Tomcat + Chrome all cold-started fresh for every repetition — that round trip apparently doesn't complete inside the hardcoded 10-second window, and did so 6/6 times, not intermittently.

Because this unrelated failure masked the actual race in every repetition, no valid before/after pass-rate comparison of the documented flicker could be obtained on this machine. Per this sweep's fail-closed rule, no code was committed (working tree is clean, nothing pushed) and no pull request was opened.

For context — Develocity facts (28d)

6 failures / 360 executions (1.7%), single exception signature (NoSuchElementException), Chrome-only (p=0.0009), concentrated in master / chrome / postgresql latest / tomcat 11-jdk25 (3/24, 12.5%) and stable-18.8.x / chrome / postgresql latest / tomcat 11-jdk25 (2/8, 25%).

Recommendation

The candidate fix above looks correct and low-risk on inspection, but needs validating with a real before/after pass-rate measurement (the repeat-run tool, xwiki-it-repeat.mjs) on a machine that isn't timing-constrained the way this sandbox was — ideally reproducing the exact NoSuchElementException signature at least once before trusting a fix for it. Leaving this open for a future sweep or a developer with access to a less constrained machine.

Posted automatically by the daily xwiki-ci-check sweep.