diff --git a/zeppelin-integration/src/test/java/org/apache/zeppelin/integration/ZeppelinIT.java b/zeppelin-integration/src/test/java/org/apache/zeppelin/integration/ZeppelinIT.java
index 745cfd284bf..ff45f123540 100644
--- a/zeppelin-integration/src/test/java/org/apache/zeppelin/integration/ZeppelinIT.java
+++ b/zeppelin-integration/src/test/java/org/apache/zeppelin/integration/ZeppelinIT.java
@@ -325,17 +325,31 @@ void testAngularRunParagraph() throws Exception {
assertTrue(isNotBlank(secondParagraphId), "Cannot find paragraph id for the 2nd paragraph");
- // Update first paragraph to call z.runParagraph() with 2nd paragraph id
- setTextOfParagraph(1,
- "%angular
Run second paragraph
");
+ + "\")'>Run second paragraph";
// Capture old output element before re-run to detect when it gets replaced
WebElement oldAngularDiv = manager.getWebDriver().findElement(By.xpath(
getParagraphXPath(1) + "//div[@id=\"angularRunParagraph\"]"));
- runParagraph(1);
+ ((JavascriptExecutor) manager.getWebDriver()).executeScript(
+ "var els = document.querySelectorAll('div[ng-controller=\"ParagraphCtrl\"]');"
+ + "var s = angular.element(els[0]).scope();"
+ + "s.paragraph.text = arguments[0];"
+ + "if (s.editor) { s.editor.setValue(arguments[0], 1); s.editor.clearSelection(); }"
+ + "s.runParagraph(arguments[0], true, false);",
+ newAngularText);
// Wait for the old output element to become stale (proves the paragraph output
// was actually refreshed, avoiding race where waitForParagraph sees the old FINISHED state)
@@ -344,9 +358,23 @@ void testAngularRunParagraph() throws Exception {
waitForParagraph(1, "FINISHED");
- // Wait for new Angular output to render
- WebElement newAngularDiv = visibilityWait(By.xpath(
- getParagraphXPath(1) + "//div[@id=\"angularRunParagraph\"]"), MAX_BROWSER_TIMEOUT_SEC);
+ // Poll for the new render: visible, expected text, and the ng-click
+ // attribute from the second version. Re-find each iteration to tolerate
+ // mid-$compile detaches; requiring ng-click rejects an empty/stale rerun
+ // where the same "Run second paragraph" string slips through.
+ final By newAngularDivLocator = By.xpath(
+ getParagraphXPath(1) + "//div[@id=\"angularRunParagraph\"]");
+ WebElement newAngularDiv = new WebDriverWait(manager.getWebDriver(),
+ Duration.ofSeconds(MAX_BROWSER_TIMEOUT_SEC))
+ .ignoring(StaleElementReferenceException.class)
+ .until(driver -> {
+ WebElement el = driver.findElement(newAngularDivLocator);
+ String ngClick = el.getAttribute("ng-click");
+ return el.isDisplayed()
+ && "Run second paragraph".equals(el.getText())
+ && ngClick != null && ngClick.contains("z.runParagraph")
+ ? el : null;
+ });
// Set new text value for 2nd paragraph
setTextOfParagraph(2, "%sh echo NEW_VALUE");