Commit 2315de34 authored by Ian Struiksma's avatar Ian Struiksma Committed by Commit Bot

Add click fallback action for autofill tests

Several sites were failing on windows autofill tests. The main issue
seems to be the resolution on windows bot that causes the sites to
sometimes render differently than when they were recorded.

One site needs different behavior for a button click on replay so
added a new action that will first check for a different element's
presence before trying to find the button to click.

Updated site recipes for 5 sites, so cipd version was updated:
sephora (removed a visibility constraint)
indigo (same)
newegg (added extra clicks to reset phone/zip fields to verify)
rue21 (rerecorded site on smaller resolution and used click fallback)
crate_and_barrel (forced payment page load)

Bug: 984664
Change-Id: Ic7d11082a2b4af53779281fcd27dce65753bac37
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1888742
Commit-Queue: Ian Struiksma <ianstruiksma@google.com>
Auto-Submit: Ian Struiksma <ianstruiksma@google.com>
Reviewed-by: default avatarDominic Battré <battre@chromium.org>
Cr-Commit-Position: refs/heads/master@{#710922}
parent 9c5365d7
......@@ -450,7 +450,7 @@ deps = {
'packages': [
{
'package': 'chromium/chrome/test/data/autofill/captured_sites',
'version': '23EuJes_tRa4KkcqAuvDc48MlYCQwVKmjv64tpGllr8C',
'version': 'o7OTl3c2uPbxtCuWl68YXFBBErGlWC8mzH8NUwAR6QwC',
}
],
'condition': 'checkout_chromium_autofill_test_dependencies',
......
......@@ -680,6 +680,10 @@ bool TestRecipeReplayer::ReplayRecordedActions(
} else if (base::CompareCaseInsensitiveASCII(*type, "click") == 0) {
if (!ExecuteClickAction(*action))
return false;
} else if (base::CompareCaseInsensitiveASCII(*type, "clickIfNotSeen") ==
0) {
if (!ExecuteClickIfNotSeenAction(*action))
return false;
} else if (base::CompareCaseInsensitiveASCII(*type, "closeTab") == 0) {
if (!ExecuteCloseTabAction(*action))
return false;
......@@ -840,6 +844,22 @@ bool TestRecipeReplayer::ExecuteClickAction(
return true;
}
bool TestRecipeReplayer::ExecuteClickIfNotSeenAction(
const base::DictionaryValue& action) {
std::string xpath;
content::RenderFrameHost* frame;
if (ExtractFrameAndVerifyElement(action, &xpath, &frame, false, false,
true)) {
return true;
} else {
const std::string* click_xpath_text =
FindPopulateString(action, "clickSelector", "click xpath selector");
base::Value click_action = action.Clone();
click_action.SetStringKey("selector", *click_xpath_text);
return ExecuteClickAction(base::Value::AsDictionaryValue(click_action));
}
}
bool TestRecipeReplayer::ExecuteCloseTabAction(
const base::DictionaryValue& action) {
VLOG(1) << "Closing Active Tab";
......@@ -1308,7 +1328,8 @@ bool TestRecipeReplayer::ExtractFrameAndVerifyElement(
std::string* xpath,
content::RenderFrameHost** frame,
bool set_focus,
bool relaxed_visibility) {
bool relaxed_visibility,
bool ignore_failure) {
if (!GetTargetHTMLElementXpathFromAction(action, xpath))
return false;
......@@ -1326,7 +1347,8 @@ bool TestRecipeReplayer::ExtractFrameAndVerifyElement(
if (relaxed_visibility)
visibility_enum_val &= ~kReadyStateOnTop;
if (!WaitForElementToBeReady(*xpath, visibility_enum_val, *frame))
if (!WaitForElementToBeReady(*xpath, visibility_enum_val, *frame,
ignore_failure))
return false;
if (set_focus) {
......@@ -1412,23 +1434,30 @@ bool TestRecipeReplayer::GetIFrameOffsetFromIFramePath(
bool TestRecipeReplayer::WaitForElementToBeReady(
const std::string& xpath,
const int visibility_enum_val,
content::RenderFrameHost* frame) {
content::RenderFrameHost* frame,
bool ignore_failure) {
std::vector<std::string> state_assertions;
state_assertions.push_back(base::StringPrintf(
"return automation_helper.isElementWithXpathReady(`%s`, %d);",
xpath.c_str(), visibility_enum_val));
return WaitForStateChange(frame, state_assertions, default_action_timeout);
return WaitForStateChange(
frame, state_assertions,
ignore_failure ? click_fallback_timeout : default_action_timeout,
ignore_failure);
}
bool TestRecipeReplayer::WaitForStateChange(
content::RenderFrameHost* frame,
const std::vector<std::string>& state_assertions,
const base::TimeDelta& timeout) {
const base::TimeDelta& timeout,
bool ignore_failure) {
base::TimeTicks start_time = base::TimeTicks::Now();
while (!AllAssertionsPassed(frame, state_assertions)) {
if (base::TimeTicks::Now() - start_time > timeout) {
if (!ignore_failure) {
ADD_FAILURE() << "State change hasn't completed within timeout.";
return false;
}
return false;
}
WaitTillPageIsIdle();
}
......
......@@ -38,6 +38,9 @@ const base::TimeDelta default_action_timeout = base::TimeDelta::FromSeconds(30);
// an action. The Captured Site Automation Framework uses this timeout to
// break out of a wait loop after a hover action.
const base::TimeDelta visual_update_timeout = base::TimeDelta::FromSeconds(20);
// The amount of time to do a precheck on the page before going to a click
// fallback action.
const base::TimeDelta click_fallback_timeout = base::TimeDelta::FromSeconds(5);
// When we cause a scroll event, make sure we give the page a moment to react
// before continuing.
const base::TimeDelta scroll_wait_timeout = base::TimeDelta::FromSeconds(2);
......@@ -250,6 +253,7 @@ class TestRecipeReplayer {
const std::unique_ptr<base::DictionaryValue>& recipe);
bool ExecuteAutofillAction(const base::DictionaryValue& action);
bool ExecuteClickAction(const base::DictionaryValue& action);
bool ExecuteClickIfNotSeenAction(const base::DictionaryValue& action);
bool ExecuteCoolOffAction(const base::DictionaryValue& action);
bool ExecuteCloseTabAction(const base::DictionaryValue& action);
bool ExecuteHoverAction(const base::DictionaryValue& action);
......@@ -281,14 +285,17 @@ class TestRecipeReplayer {
std::string* xpath,
content::RenderFrameHost** frame,
bool set_focus = false,
bool relaxed_visibility = false);
bool relaxed_visibility = false,
bool ignore_failure = false);
bool WaitForElementToBeReady(const std::string& xpath,
const int visibility_enum_val,
content::RenderFrameHost* frame);
content::RenderFrameHost* frame,
bool ignore_failure = false);
bool WaitForStateChange(
content::RenderFrameHost* frame,
const std::vector<std::string>& state_assertions,
const base::TimeDelta& timeout = default_action_timeout);
const base::TimeDelta& timeout = default_action_timeout,
bool ignore_failure = false);
bool AllAssertionsPassed(const content::ToRenderFrameHost& frame,
const std::vector<std::string>& assertions);
bool ExecuteJavaScriptOnElementByXpath(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment