Fix flaky web driver tests (#784)

* Fix flaky web driver tests

Identified two flaky tests in RegistrarConsoleScreenshotTest through
local testing and fixed them by waiting for specific web elements instead
of using fixed delays.

Refactored the wait methods to support different test scenarios,
and removed unnecessary delays.

Extensively tested locally. Also ran multiple presubmits on Kokoro.
This commit is contained in:
Weimin Yu 2020-08-31 15:09:54 -04:00 committed by GitHub
parent bbcafea98e
commit 5db8cbc994
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 111 additions and 98 deletions

View file

@ -41,7 +41,7 @@ public class OteSetupConsoleScreenshotTest extends WebDriverTestCase {
@RetryingTest(3) @RetryingTest(3)
void get_owner_fails() throws Throwable { void get_owner_fails() throws Throwable {
driver.get(server.getUrl("/registrar-ote-setup")); driver.get(server.getUrl("/registrar-ote-setup"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("unauthorized"); driver.diffPage("unauthorized");
} }
@ -49,14 +49,14 @@ public class OteSetupConsoleScreenshotTest extends WebDriverTestCase {
void get_admin_succeeds() throws Throwable { void get_admin_succeeds() throws Throwable {
server.setIsAdmin(true); server.setIsAdmin(true);
driver.get(server.getUrl("/registrar-ote-setup")); driver.get(server.getUrl("/registrar-ote-setup"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("formEmpty"); driver.diffPage("formEmpty");
driver.findElement(By.id("clientId")).sendKeys("acmereg"); driver.findElement(By.id("clientId")).sendKeys("acmereg");
driver.findElement(By.id("email")).sendKeys("acmereg@registry.example"); driver.findElement(By.id("email")).sendKeys("acmereg@registry.example");
driver.findElement(By.id("password")).sendKeys("StRoNgPaSsWoRd"); driver.findElement(By.id("password")).sendKeys("StRoNgPaSsWoRd");
driver.diffPage("formFilled"); driver.diffPage("formFilled");
driver.findElement(By.id("submit-button")).click(); driver.findElement(By.id("submit-button")).click();
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("oteResult"); driver.diffPage("oteResult");
} }
@ -64,11 +64,11 @@ public class OteSetupConsoleScreenshotTest extends WebDriverTestCase {
void get_admin_fails_badEmail() throws Throwable { void get_admin_fails_badEmail() throws Throwable {
server.setIsAdmin(true); server.setIsAdmin(true);
driver.get(server.getUrl("/registrar-ote-setup")); driver.get(server.getUrl("/registrar-ote-setup"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.findElement(By.id("clientId")).sendKeys("acmereg"); driver.findElement(By.id("clientId")).sendKeys("acmereg");
driver.findElement(By.id("email")).sendKeys("bad email"); driver.findElement(By.id("email")).sendKeys("bad email");
driver.findElement(By.id("submit-button")).click(); driver.findElement(By.id("submit-button")).click();
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("oteResultFailed"); driver.diffPage("oteResultFailed");
} }
} }

View file

@ -68,7 +68,7 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
@RetryingTest(3) @RetryingTest(3)
void index_owner() throws Throwable { void index_owner() throws Throwable {
driver.get(server.getUrl("/registrar")); driver.get(server.getUrl("/registrar"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("page"); driver.diffPage("page");
} }
@ -77,7 +77,7 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
void index_adminAndOwner() throws Throwable { void index_adminAndOwner() throws Throwable {
server.setIsAdmin(true); server.setIsAdmin(true);
driver.get(server.getUrl("/registrar")); driver.get(server.getUrl("/registrar"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("page"); driver.diffPage("page");
} }
@ -88,22 +88,21 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
// To make sure we're only ADMIN (and not also "OWNER"), we switch to the NewRegistrar we // To make sure we're only ADMIN (and not also "OWNER"), we switch to the NewRegistrar we
// aren't in the contacts of // aren't in the contacts of
driver.get(server.getUrl("/registrar?clientId=NewRegistrar")); driver.get(server.getUrl("/registrar?clientId=NewRegistrar"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("page"); driver.diffPage("page");
} }
@RetryingTest(3) @RetryingTest(3)
void contactUs() throws Throwable { void contactUs() throws Throwable {
driver.get(server.getUrl("/registrar#contact-us")); driver.get(server.getUrl("/registrar#contact-us"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("page"); driver.diffPage("page");
} }
@RetryingTest(3) @RetryingTest(3)
void settingsContact() throws Throwable { void settingsContact() throws Throwable {
driver.get(server.getUrl("/registrar#contact-settings")); driver.get(server.getUrl("/registrar#contact-settings"));
Thread.sleep(1000); driver.waitForDisplayedElement(By.tagName("h1"));
driver.waitForElement(By.tagName("h1"));
driver.diffPage("page"); driver.diffPage("page");
} }
@ -112,16 +111,14 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
void settingsContact_asAdmin() throws Throwable { void settingsContact_asAdmin() throws Throwable {
server.setIsAdmin(true); server.setIsAdmin(true);
driver.get(server.getUrl("/registrar?clientId=NewRegistrar#contact-settings")); driver.get(server.getUrl("/registrar?clientId=NewRegistrar#contact-settings"));
Thread.sleep(1000); driver.waitForDisplayedElement(By.tagName("h1"));
driver.waitForElement(By.tagName("h1"));
driver.diffPage("page"); driver.diffPage("page");
} }
@RetryingTest(3) @RetryingTest(3)
void settingsContactItem() throws Throwable { void settingsContactItem() throws Throwable {
driver.get(server.getUrl("/registrar#contact-settings/johndoe@theregistrar.com")); driver.get(server.getUrl("/registrar#contact-settings/johndoe@theregistrar.com"));
Thread.sleep(1000); driver.waitForDisplayedElement(By.tagName("h1"));
driver.waitForElement(By.tagName("h1"));
driver.diffPage("page"); driver.diffPage("page");
} }
@ -132,8 +129,7 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
driver.get( driver.get(
server.getUrl( server.getUrl(
"/registrar?clientId=NewRegistrar#contact-settings/janedoe@theregistrar.com")); "/registrar?clientId=NewRegistrar#contact-settings/janedoe@theregistrar.com"));
Thread.sleep(1000); driver.waitForDisplayedElement(By.tagName("h1"));
driver.waitForElement(By.tagName("h1"));
driver.diffPage("page"); driver.diffPage("page");
} }
@ -141,9 +137,8 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
void settingsContactEdit() throws Throwable { void settingsContactEdit() throws Throwable {
driver.manage().window().setSize(new Dimension(1050, 2000)); driver.manage().window().setSize(new Dimension(1050, 2000));
driver.get(server.getUrl("/registrar#contact-settings/johndoe@theregistrar.com")); driver.get(server.getUrl("/registrar#contact-settings/johndoe@theregistrar.com"));
Thread.sleep(1000); driver.waitForDisplayedElement(By.tagName("h1"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.id("reg-app-btn-edit")).click();
driver.waitForElement(By.id("reg-app-btn-edit")).click();
driver.diffPage("page"); driver.diffPage("page");
} }
@ -162,9 +157,8 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
}); });
driver.manage().window().setSize(new Dimension(1050, 2000)); driver.manage().window().setSize(new Dimension(1050, 2000));
driver.get(server.getUrl("/registrar#contact-settings/johndoe@theregistrar.com")); driver.get(server.getUrl("/registrar#contact-settings/johndoe@theregistrar.com"));
Thread.sleep(1000); driver.waitForDisplayedElement(By.tagName("h1"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.id("reg-app-btn-edit")).click();
driver.waitForElement(By.id("reg-app-btn-edit")).click();
// The password should show as dots when the user types it in // The password should show as dots when the user types it in
driver.findElement(By.id("contacts[1].registryLockPassword")).sendKeys("password"); driver.findElement(By.id("contacts[1].registryLockPassword")).sendKeys("password");
driver.diffPage("page_with_password"); driver.diffPage("page_with_password");
@ -179,9 +173,10 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
Thread.sleep(5); Thread.sleep(5);
driver.diffPage("page_with_password_after_hide"); driver.diffPage("page_with_password_after_hide");
// now actually set the password // Now click the Save button and wait for another Edit button to show up
driver.waitForElement(By.id("reg-app-btn-save")).click(); driver.waitForRefreshedElementAfterAction(
Thread.sleep(500); () -> driver.waitForDisplayedElement(By.id("reg-app-btn-save")).click(),
By.id("reg-app-btn-edit"));
driver.diffPage("contact_view"); driver.diffPage("contact_view");
server.runInAppEngineEnvironment( server.runInAppEngineEnvironment(
@ -213,9 +208,8 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
}); });
driver.manage().window().setSize(new Dimension(1050, 2000)); driver.manage().window().setSize(new Dimension(1050, 2000));
driver.get(server.getUrl("/registrar#contact-settings/johndoe@theregistrar.com")); driver.get(server.getUrl("/registrar#contact-settings/johndoe@theregistrar.com"));
Thread.sleep(1000); driver.waitForDisplayedElement(By.tagName("h1"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.id("reg-app-btn-edit")).click();
driver.waitForElement(By.id("reg-app-btn-edit")).click();
driver.diffPage("page"); driver.diffPage("page");
} }
@ -225,9 +219,8 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
() -> persistResource(makeRegistrar2().asBuilder().setRegistryLockAllowed(true).build())); () -> persistResource(makeRegistrar2().asBuilder().setRegistryLockAllowed(true).build()));
driver.manage().window().setSize(new Dimension(1050, 2000)); driver.manage().window().setSize(new Dimension(1050, 2000));
driver.get(server.getUrl("/registrar#contact-settings/johndoe@theregistrar.com")); driver.get(server.getUrl("/registrar#contact-settings/johndoe@theregistrar.com"));
Thread.sleep(1000); driver.waitForDisplayedElement(By.tagName("h1"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.id("reg-app-btn-edit")).click();
driver.waitForElement(By.id("reg-app-btn-edit")).click();
driver.diffPage("page"); driver.diffPage("page");
} }
@ -235,9 +228,8 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
void settingsContactAdd() throws Throwable { void settingsContactAdd() throws Throwable {
driver.manage().window().setSize(new Dimension(1050, 2000)); driver.manage().window().setSize(new Dimension(1050, 2000));
driver.get(server.getUrl("/registrar#contact-settings")); driver.get(server.getUrl("/registrar#contact-settings"));
Thread.sleep(1000); driver.waitForDisplayedElement(By.tagName("h1"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.id("reg-app-btn-add")).click();
driver.waitForElement(By.id("reg-app-btn-add")).click();
// Attempt to fix flaky tests. The going theory is that the click button CSS animation needs to // Attempt to fix flaky tests. The going theory is that the click button CSS animation needs to
// finish before the screenshot is captured. // finish before the screenshot is captured.
Thread.sleep(250); Thread.sleep(250);
@ -251,10 +243,10 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
// To make sure we're only ADMIN (and not also "OWNER"), we switch to the NewRegistrar we // To make sure we're only ADMIN (and not also "OWNER"), we switch to the NewRegistrar we
// aren't in the contacts of // aren't in the contacts of
driver.get(server.getUrl("/registrar?clientId=NewRegistrar#admin-settings")); driver.get(server.getUrl("/registrar?clientId=NewRegistrar#admin-settings"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("view"); driver.diffPage("view");
driver.waitForElement(By.id("reg-app-btn-edit")).click(); driver.waitForDisplayedElement(By.id("reg-app-btn-edit")).click();
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("edit"); driver.diffPage("edit");
} }
@ -272,7 +264,7 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
void settingsAdmin_whenNotAdmin_showsHome() throws Throwable { void settingsAdmin_whenNotAdmin_showsHome() throws Throwable {
driver.manage().window().setSize(new Dimension(1050, 2000)); driver.manage().window().setSize(new Dimension(1050, 2000));
driver.get(server.getUrl("/registrar#admin-settings")); driver.get(server.getUrl("/registrar#admin-settings"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("view"); driver.diffPage("view");
} }
@ -280,7 +272,7 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
void getOteStatus_noButtonWhenReal() throws Exception { void getOteStatus_noButtonWhenReal() throws Exception {
server.setIsAdmin(true); server.setIsAdmin(true);
driver.get(server.getUrl("/registrar#admin-settings")); driver.get(server.getUrl("/registrar#admin-settings"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("result"); driver.diffPage("result");
} }
@ -299,7 +291,7 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
void getOteStatus_completed() throws Exception { void getOteStatus_completed() throws Exception {
server.setIsAdmin(true); server.setIsAdmin(true);
driver.get(server.getUrl("/registrar?clientId=otefinished-1#admin-settings")); driver.get(server.getUrl("/registrar?clientId=otefinished-1#admin-settings"));
driver.waitForElement(By.id("btn-ote-status")); driver.waitForDisplayedElement(By.id("btn-ote-status"));
driver.diffPage("before_click"); driver.diffPage("before_click");
driver.findElement(By.id("btn-ote-status")).click(); driver.findElement(By.id("btn-ote-status")).click();
driver.findElement(By.id("ote-results-table")).click(); driver.findElement(By.id("ote-results-table")).click();
@ -312,10 +304,10 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
void settingsSecurity() throws Throwable { void settingsSecurity() throws Throwable {
driver.manage().window().setSize(new Dimension(1050, 2000)); driver.manage().window().setSize(new Dimension(1050, 2000));
driver.get(server.getUrl("/registrar#security-settings")); driver.get(server.getUrl("/registrar#security-settings"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("view"); driver.diffPage("view");
driver.waitForElement(By.id("reg-app-btn-edit")).click(); driver.waitForDisplayedElement(By.id("reg-app-btn-edit")).click();
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("edit"); driver.diffPage("edit");
} }
@ -325,7 +317,7 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
server.setIsAdmin(true); server.setIsAdmin(true);
driver.manage().window().setSize(new Dimension(1050, 2000)); driver.manage().window().setSize(new Dimension(1050, 2000));
driver.get(server.getUrl("/registrar?clientId=NewRegistrar#security-settings")); driver.get(server.getUrl("/registrar?clientId=NewRegistrar#security-settings"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("view"); driver.diffPage("view");
} }
@ -343,10 +335,10 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
}); });
driver.manage().window().setSize(new Dimension(1050, 2000)); driver.manage().window().setSize(new Dimension(1050, 2000));
driver.get(server.getUrl("/registrar#security-settings")); driver.get(server.getUrl("/registrar#security-settings"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("view"); driver.diffPage("view");
driver.waitForElement(By.id("reg-app-btn-edit")).click(); driver.waitForDisplayedElement(By.id("reg-app-btn-edit")).click();
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("edit"); driver.diffPage("edit");
} }
@ -363,10 +355,10 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
}); });
driver.manage().window().setSize(new Dimension(1050, 2000)); driver.manage().window().setSize(new Dimension(1050, 2000));
driver.get(server.getUrl("/registrar#security-settings")); driver.get(server.getUrl("/registrar#security-settings"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("view"); driver.diffPage("view");
driver.waitForElement(By.id("reg-app-btn-edit")).click(); driver.waitForDisplayedElement(By.id("reg-app-btn-edit")).click();
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("edit"); driver.diffPage("edit");
} }
@ -377,14 +369,14 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
persistResource( persistResource(
loadRegistrar("TheRegistrar").asBuilder().setState(State.DISABLED).build())); loadRegistrar("TheRegistrar").asBuilder().setState(State.DISABLED).build()));
driver.get(server.getUrl("/registrar")); driver.get(server.getUrl("/registrar"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("view"); driver.diffPage("view");
} }
@RetryingTest(3) @RetryingTest(3)
void settingsWhois() throws Throwable { void settingsWhois() throws Throwable {
driver.get(server.getUrl("/registrar#whois-settings")); driver.get(server.getUrl("/registrar#whois-settings"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("page"); driver.diffPage("page");
} }
@ -392,8 +384,8 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
void settingsWhoisEdit() throws Throwable { void settingsWhoisEdit() throws Throwable {
driver.manage().window().setSize(new Dimension(1050, 2000)); driver.manage().window().setSize(new Dimension(1050, 2000));
driver.get(server.getUrl("/registrar#whois-settings")); driver.get(server.getUrl("/registrar#whois-settings"));
driver.waitForElement(By.id("reg-app-btn-edit")).click(); driver.waitForDisplayedElement(By.id("reg-app-btn-edit")).click();
Thread.sleep(1000); driver.waitForDisplayedElement(By.id("reg-app-btn-save"));
driver.diffPage("page"); driver.diffPage("page");
} }
@ -401,10 +393,12 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
void settingsWhoisEditError() throws Throwable { void settingsWhoisEditError() throws Throwable {
driver.manage().window().setSize(new Dimension(1050, 2000)); driver.manage().window().setSize(new Dimension(1050, 2000));
driver.get(server.getUrl("/registrar#whois-settings")); driver.get(server.getUrl("/registrar#whois-settings"));
driver.waitForElement(By.id("reg-app-btn-edit")).click(); driver.waitForDisplayedElement(By.id("reg-app-btn-edit")).click();
driver.setFormFieldsById(ImmutableMap.of("faxNumber", "cat")); driver.setFormFieldsById(ImmutableMap.of("faxNumber", "cat"));
driver.waitForElement(By.id("reg-app-btn-save")).click(); driver.waitForDisplayedElement(By.id("reg-app-btn-save")).click();
Thread.sleep(1000); // After the click, a div element without id would show up with an error message.
driver.waitForElementWithCondition(
By.tagName("div"), e -> e.getText().startsWith("Must be a valid +E.164 phone number,"));
driver.diffPage("page"); driver.diffPage("page");
} }
@ -412,7 +406,7 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
void indexPage_smallScrolledDown() throws Throwable { void indexPage_smallScrolledDown() throws Throwable {
driver.manage().window().setSize(new Dimension(600, 300)); driver.manage().window().setSize(new Dimension(600, 300));
driver.get(server.getUrl("/registrar")); driver.get(server.getUrl("/registrar"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.executeScript("document.getElementById('reg-content-and-footer').scrollTop = 200"); driver.executeScript("document.getElementById('reg-content-and-footer').scrollTop = 200");
Thread.sleep(500); Thread.sleep(500);
driver.diffPage("page"); driver.diffPage("page");
@ -439,21 +433,21 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
driver.get( driver.get(
server.getUrl( server.getUrl(
"/registry-lock-verify?isLock=true&lockVerificationCode=" + lockVerificationCode)); "/registry-lock-verify?isLock=true&lockVerificationCode=" + lockVerificationCode));
driver.waitForElement(By.id("reg-content")); driver.waitForDisplayedElement(By.id("reg-content"));
driver.diffPage("page"); driver.diffPage("page");
} }
@RetryingTest(3) @RetryingTest(3)
void registryLockVerify_unknownLock() throws Throwable { void registryLockVerify_unknownLock() throws Throwable {
driver.get(server.getUrl("/registry-lock-verify?isLock=true&lockVerificationCode=asdfasdf")); driver.get(server.getUrl("/registry-lock-verify?isLock=true&lockVerificationCode=asdfasdf"));
driver.waitForElement(By.id("reg-content")); driver.waitForDisplayedElement(By.id("reg-content"));
driver.diffPage("page"); driver.diffPage("page");
} }
@RetryingTest(3) @RetryingTest(3)
void registryLock_empty() throws Throwable { void registryLock_empty() throws Throwable {
driver.get(server.getUrl("/registrar?clientId=TheRegistrar#registry-lock")); driver.get(server.getUrl("/registrar?clientId=TheRegistrar#registry-lock"));
driver.waitForElement(By.tagName("h2")); driver.waitForDisplayedElement(By.tagName("h2"));
driver.diffPage("page"); driver.diffPage("page");
} }
@ -465,7 +459,7 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
return null; return null;
}); });
driver.get(server.getUrl("/registrar?clientId=TheRegistrar#registry-lock")); driver.get(server.getUrl("/registrar?clientId=TheRegistrar#registry-lock"));
driver.waitForElement(By.tagName("h2")); driver.waitForDisplayedElement(By.tagName("h2"));
driver.diffPage("page"); driver.diffPage("page");
} }
@ -477,7 +471,7 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
return null; return null;
}); });
driver.get(server.getUrl("/registrar#registry-lock")); driver.get(server.getUrl("/registrar#registry-lock"));
driver.waitForElement(By.tagName("h2")); driver.waitForDisplayedElement(By.tagName("h2"));
driver.diffPage("page"); driver.diffPage("page");
} }
@ -530,7 +524,7 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
return null; return null;
}); });
driver.get(server.getUrl("/registrar#registry-lock")); driver.get(server.getUrl("/registrar#registry-lock"));
driver.waitForElement(By.tagName("h2")); driver.waitForDisplayedElement(By.tagName("h2"));
driver.diffPage("page"); driver.diffPage("page");
} }
@ -542,9 +536,9 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
return null; return null;
}); });
driver.get(server.getUrl("/registrar#registry-lock")); driver.get(server.getUrl("/registrar#registry-lock"));
driver.waitForElement(By.tagName("h2")); driver.waitForDisplayedElement(By.tagName("h2"));
driver.findElement(By.id("button-unlock-example.tld")).click(); driver.findElement(By.id("button-unlock-example.tld")).click();
driver.waitForElement(By.className("modal-content")); driver.waitForDisplayedElement(By.className("modal-content"));
driver.findElement(By.id("domain-lock-password")).sendKeys("password"); driver.findElement(By.id("domain-lock-password")).sendKeys("password");
driver.diffPage("page"); driver.diffPage("page");
} }
@ -559,9 +553,9 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
return null; return null;
}); });
driver.get(server.getUrl("/registrar#registry-lock")); driver.get(server.getUrl("/registrar#registry-lock"));
driver.waitForElement(By.tagName("h2")); driver.waitForDisplayedElement(By.tagName("h2"));
driver.findElement(By.id("button-lock-domain")).click(); driver.findElement(By.id("button-lock-domain")).click();
driver.waitForElement(By.className("modal-content")); driver.waitForDisplayedElement(By.className("modal-content"));
driver.findElement(By.id("domain-lock-input-value")).sendKeys("somedomain.tld"); driver.findElement(By.id("domain-lock-input-value")).sendKeys("somedomain.tld");
driver.diffPage("page"); driver.diffPage("page");
} }
@ -578,7 +572,7 @@ class RegistrarConsoleScreenshotTest extends WebDriverTestCase {
return null; return null;
}); });
driver.get(server.getUrl("/registrar?clientId=TheRegistrar#registry-lock")); driver.get(server.getUrl("/registrar?clientId=TheRegistrar#registry-lock"));
driver.waitForElement(By.tagName("h2")); driver.waitForDisplayedElement(By.tagName("h2"));
driver.diffPage("page"); driver.diffPage("page");
} }

View file

@ -55,7 +55,7 @@ public class RegistrarConsoleWebTest extends WebDriverTestCase {
/** Checks that an element is visible. */ /** Checks that an element is visible. */
void assertEltVisible(String eltId) throws Throwable { void assertEltVisible(String eltId) throws Throwable {
assertThat(driver.waitForElement(By.id(eltId)).isDisplayed()).isTrue(); assertThat(driver.waitForDisplayedElement(By.id(eltId)).isDisplayed()).isTrue();
} }
/** Checks that an element is invisible. */ /** Checks that an element is invisible. */
@ -141,7 +141,7 @@ public class RegistrarConsoleWebTest extends WebDriverTestCase {
@RetryingTest(3) @RetryingTest(3)
void testWhoisSettingsEdit() throws Throwable { void testWhoisSettingsEdit() throws Throwable {
driver.get(server.getUrl("/registrar#whois-settings")); driver.get(server.getUrl("/registrar#whois-settings"));
driver.waitForElement(By.id("reg-app-btn-edit")).click(); driver.waitForDisplayedElement(By.id("reg-app-btn-edit")).click();
driver.setFormFieldsById( driver.setFormFieldsById(
new ImmutableMap.Builder<String, String>() new ImmutableMap.Builder<String, String>()
.put("emailAddress", "test1@example.com") .put("emailAddress", "test1@example.com")
@ -178,7 +178,7 @@ public class RegistrarConsoleWebTest extends WebDriverTestCase {
@RetryingTest(3) @RetryingTest(3)
void testContactSettingsView() throws Throwable { void testContactSettingsView() throws Throwable {
driver.get(server.getUrl("/registrar#contact-settings")); driver.get(server.getUrl("/registrar#contact-settings"));
driver.waitForElement(By.id("reg-app-btn-add")); driver.waitForDisplayedElement(By.id("reg-app-btn-add"));
ImmutableList<RegistrarContact> contacts = ImmutableList<RegistrarContact> contacts =
server.runInAppEngineEnvironment( server.runInAppEngineEnvironment(
() -> loadRegistrar("TheRegistrar").getContacts().asList()); () -> loadRegistrar("TheRegistrar").getContacts().asList());
@ -192,7 +192,7 @@ public class RegistrarConsoleWebTest extends WebDriverTestCase {
@RetryingTest(3) @RetryingTest(3)
void testSecuritySettingsView() throws Throwable { void testSecuritySettingsView() throws Throwable {
driver.get(server.getUrl("/registrar#security-settings")); driver.get(server.getUrl("/registrar#security-settings"));
driver.waitForElement(By.id("reg-app-btn-edit")); driver.waitForDisplayedElement(By.id("reg-app-btn-edit"));
Registrar registrar = server.runInAppEngineEnvironment(() -> loadRegistrar("TheRegistrar")); Registrar registrar = server.runInAppEngineEnvironment(() -> loadRegistrar("TheRegistrar"));
assertThat(driver.findElement(By.id("phonePasscode")).getAttribute("value")) assertThat(driver.findElement(By.id("phonePasscode")).getAttribute("value"))
.isEqualTo(registrar.getPhonePasscode()); .isEqualTo(registrar.getPhonePasscode());

View file

@ -41,7 +41,7 @@ class RegistrarCreateConsoleScreenshotTest extends WebDriverTestCase {
@RetryingTest(3) @RetryingTest(3)
void get_owner_fails() throws Throwable { void get_owner_fails() throws Throwable {
driver.get(server.getUrl("/registrar-create")); driver.get(server.getUrl("/registrar-create"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("unauthorized"); driver.diffPage("unauthorized");
} }
@ -49,7 +49,7 @@ class RegistrarCreateConsoleScreenshotTest extends WebDriverTestCase {
void get_admin_succeeds() throws Throwable { void get_admin_succeeds() throws Throwable {
server.setIsAdmin(true); server.setIsAdmin(true);
driver.get(server.getUrl("/registrar-create")); driver.get(server.getUrl("/registrar-create"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("formEmpty"); driver.diffPage("formEmpty");
driver.findElement(By.id("clientId")).sendKeys("my-name"); driver.findElement(By.id("clientId")).sendKeys("my-name");
driver.findElement(By.id("name")).sendKeys("registrar name"); driver.findElement(By.id("name")).sendKeys("registrar name");
@ -69,7 +69,7 @@ class RegistrarCreateConsoleScreenshotTest extends WebDriverTestCase {
driver.findElement(By.id("passcode")).sendKeys("01234"); driver.findElement(By.id("passcode")).sendKeys("01234");
driver.diffPage("formFilled"); driver.diffPage("formFilled");
driver.findElement(By.id("submit-button")).click(); driver.findElement(By.id("submit-button")).click();
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("createResult"); driver.diffPage("createResult");
} }
@ -77,7 +77,7 @@ class RegistrarCreateConsoleScreenshotTest extends WebDriverTestCase {
void get_admin_fails_badEmail() throws Throwable { void get_admin_fails_badEmail() throws Throwable {
server.setIsAdmin(true); server.setIsAdmin(true);
driver.get(server.getUrl("/registrar-create")); driver.get(server.getUrl("/registrar-create"));
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.findElement(By.id("clientId")).sendKeys("my-name"); driver.findElement(By.id("clientId")).sendKeys("my-name");
driver.findElement(By.id("name")).sendKeys("registrar name"); driver.findElement(By.id("name")).sendKeys("registrar name");
driver driver
@ -93,7 +93,7 @@ class RegistrarCreateConsoleScreenshotTest extends WebDriverTestCase {
driver.findElement(By.id("city")).sendKeys("Citysville"); driver.findElement(By.id("city")).sendKeys("Citysville");
driver.findElement(By.id("countryCode")).sendKeys("fr"); driver.findElement(By.id("countryCode")).sendKeys("fr");
driver.findElement(By.id("submit-button")).click(); driver.findElement(By.id("submit-button")).click();
driver.waitForElement(By.tagName("h1")); driver.waitForDisplayedElement(By.tagName("h1"));
driver.diffPage("createResultFailed"); driver.diffPage("createResultFailed");
} }
} }

View file

@ -19,9 +19,11 @@ import static java.util.stream.Collectors.joining;
import static org.apache.commons.text.StringEscapeUtils.escapeEcmaScript; import static org.apache.commons.text.StringEscapeUtils.escapeEcmaScript;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.base.Predicates;
import java.net.URL; import java.net.URL;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Predicate; import java.util.function.Predicate;
@ -34,6 +36,7 @@ import org.openqa.selenium.Dimension;
import org.openqa.selenium.HasCapabilities; import org.openqa.selenium.HasCapabilities;
import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.OutputType; import org.openqa.selenium.OutputType;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WebDriverException;
@ -55,7 +58,6 @@ public final class WebDriverPlusScreenDifferExtension
HasCapabilities { HasCapabilities {
private static final int WAIT_FOR_ELEMENTS_POLLING_INTERVAL_MS = 10; private static final int WAIT_FOR_ELEMENTS_POLLING_INTERVAL_MS = 10;
private static final int WAIT_FOR_ELEMENTS_BONUS_DELAY_MS = 150;
// The maximum difference between pixels that would be considered as "identical". Calculated as // The maximum difference between pixels that would be considered as "identical". Calculated as
// the sum of the absolute difference between the values of the RGB channels. So a 120,30,200 // the sum of the absolute difference between the values of the RGB channels. So a 120,30,200
@ -121,28 +123,40 @@ public final class WebDriverPlusScreenDifferExtension
driver.get(url.toString()); driver.get(url.toString());
} }
/** Waits indefinitely for an element to appear on the page, then returns it. */ /** Waits indefinitely for a <em>visible</em> element matching {@code by}, then returns it. */
WebElement waitForElement(By by) throws InterruptedException { WebElement waitForDisplayedElement(By by) throws InterruptedException {
while (true) { return waitForElementWithCondition(by, WebElement::isDisplayed);
List<WebElement> elements = findElements(by);
if (!elements.isEmpty()) {
Thread.sleep(WAIT_FOR_ELEMENTS_BONUS_DELAY_MS);
return elements.get(0);
}
Thread.sleep(WAIT_FOR_ELEMENTS_POLLING_INTERVAL_MS);
}
} }
/** Waits for element matching {@code by} whose {@code attribute} satisfies {@code predicate}. */ /** Waits indefinitely for an element matching {@code by}, then returns it. */
public WebElement waitForAttribute( WebElement waitForElement(By by) throws InterruptedException {
By by, String attribute, Predicate</*@Nullable*/ ? super CharSequence> predicate) return waitForElementWithCondition(by, Predicates.alwaysTrue());
}
/**
* Executes an action and waits indefinitely for the replacement of an <em>existing</em> element.
*/
WebElement waitForRefreshedElementAfterAction(ThrowingRunnable action, By by) throws Exception {
WebElement element = findElement(by);
action.run();
while (true) {
try {
element.isDisplayed(); // Eventually triggers StaleElementReferenceException
Thread.sleep(WAIT_FOR_ELEMENTS_POLLING_INTERVAL_MS);
} catch (StaleElementReferenceException e) {
break;
}
}
return waitForDisplayedElement(by);
}
/** Waits for an element matching {@code by} and satisfying {@code predicate}, then returns it. */
WebElement waitForElementWithCondition(By by, Predicate<WebElement> predicate)
throws InterruptedException { throws InterruptedException {
while (true) { while (true) {
for (WebElement element : findElements(by)) { Optional<WebElement> firstMatch = findElements(by).stream().filter(predicate).findFirst();
if (predicate.test(element.getAttribute(attribute))) { if (firstMatch.isPresent()) {
Thread.sleep(WAIT_FOR_ELEMENTS_BONUS_DELAY_MS); return firstMatch.get();
return element;
}
} }
Thread.sleep(WAIT_FOR_ELEMENTS_POLLING_INTERVAL_MS); Thread.sleep(WAIT_FOR_ELEMENTS_POLLING_INTERVAL_MS);
} }
@ -303,4 +317,9 @@ public final class WebDriverPlusScreenDifferExtension
Preconditions.checkNotNull(imageNamePrefix); Preconditions.checkNotNull(imageNamePrefix);
return imageNamePrefix + "_" + imageKey; return imageNamePrefix + "_" + imageKey;
} }
public interface ThrowingRunnable {
void run() throws Exception;
}
} }