Commit de0ebb0d authored by Clemens Arbesser's avatar Clemens Arbesser Committed by Commit Bot

[Autofill Assistant] Added new trigger script integration test.

This adds an integration test, testing changing element conditions.

This CL also fixes several bugs that were discovered during testing:
- Fixed issue where ElementConditions were not correctly added and
cleared.
- Constructing a new instance of AssistantHeaderCoordinator no longer
has a side effect in AssistantHeaderModel.
- Fixed a possible crash when showing a new trigger script while another
was in the process of being hidden (crash comes down to timing). The fix
is to always create a new BottomSheetContent, instead of re-populating
the old one.

Bug: b/171776026
Change-Id: I7eac6673100ab21d459ec7f1ed200b2be9a44ff5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2524532
Commit-Queue: Clemens Arbesser <arbesser@google.com>
Reviewed-by: default avatarMarian Fechete <marianfe@google.com>
Cr-Commit-Position: refs/heads/master@{#826379}
parent c346bce7
......@@ -293,7 +293,6 @@ android_library("test_java") {
"javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPromptNavigationIntegrationTest.java",
"javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantTextUtilsTest.java",
"javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantTriggerScriptIntegrationTest.java",
"javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantTriggerScriptTest.java",
"javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java",
"javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTestUtil.java",
"javatests/src/org/chromium/chrome/browser/autofill_assistant/TestingAutofillAssistantModuleEntryProvider.java",
......
......@@ -53,11 +53,10 @@ public class AutofillAssistantModuleEntryImpl implements AutofillAssistantModule
// Start trigger script and transition to regular flow on success.
if (TextUtils.equals(parameters.get(PARAMETER_REQUEST_TRIGGER_SCRIPT), "true")) {
AssistantTriggerScriptBridge triggerScriptController =
AssistantTriggerScriptBridge triggerScriptBridge =
new AssistantTriggerScriptBridge();
triggerScriptController.start(bottomSheetController, context, webContents,
initialUrl, parameters, experimentIds,
new AssistantTriggerScriptBridge.Delegate() {
triggerScriptBridge.start(bottomSheetController, context, webContents, initialUrl,
parameters, experimentIds, new AssistantTriggerScriptBridge.Delegate() {
@Override
public void onTriggerScriptFinished(
@LiteScriptFinishedState int finishedState) {
......@@ -109,7 +108,6 @@ public class AutofillAssistantModuleEntryImpl implements AutofillAssistantModule
return !TextUtils.isEmpty(parameters.get(PARAMETER_TRIGGER_FIRST_TIME_USER))
|| TextUtils.equals(parameters.get(PARAMETER_REQUEST_TRIGGER_SCRIPT), "true");
}
/**
* Starts a 'lite' autofill assistant script in the background. Does not show the onboarding.
* Does not have access to any information aside from the trigger script paths. Calls {@code
......
......@@ -111,8 +111,6 @@ public class AssistantHeaderCoordinator implements ProfileDataCache.Observer {
new AssistantHeaderViewBinder.ViewHolder(context, mView, poodle, mChipsContainer);
AssistantHeaderViewBinder viewBinder = new AssistantHeaderViewBinder();
PropertyModelChangeProcessor.create(model, mViewHolder, viewBinder);
model.set(AssistantHeaderModel.PROGRESS_VISIBLE, true);
}
@Override
......
......@@ -60,6 +60,7 @@ public class AssistantHeaderModel extends PropertyModel {
PROGRESS_VISIBLE, USE_STEP_PROGRESS_BAR, STEP_PROGRESS_BAR_ICONS, SPIN_POODLE,
FEEDBACK_BUTTON_CALLBACK, CHIPS, CHIPS_VISIBLE, DISABLE_ANIMATIONS_FOR_TESTING);
set(CHIPS, new ArrayList<>());
set(PROGRESS_VISIBLE, true);
}
@CalledByNative
......
......@@ -45,17 +45,15 @@ public class AssistantTriggerScript {
}
@Nullable
private final AssistantBottomSheetContent mContent;
private AssistantBottomSheetContent mContent;
private final Context mContext;
private final Delegate mDelegate;
private final BottomSheetController mBottomSheetController;
private final BottomSheetObserver mBottomSheetObserver;
private final AssistantRootViewContainer mRootViewContainer;
private final ScrollView mScrollableContent;
private final AssistantHeaderCoordinator mHeaderCoordinator;
private final AssistantHeaderModel mHeaderModel;
private final LinearLayout mChipsContainer;
private AssistantHeaderCoordinator mHeaderCoordinator;
private final AssistantHeaderModel mHeaderModel = new AssistantHeaderModel();
private LinearLayout mChipsContainer;
private final int mInnerChipSpacing;
private final List<AssistantChip> mLeftAlignedChips = new ArrayList<>();
......@@ -80,7 +78,13 @@ public class AssistantTriggerScript {
}
}
};
mInnerChipSpacing = mContext.getResources().getDimensionPixelSize(
R.dimen.autofill_assistant_actions_spacing);
mHeaderModel.set(
AssistantHeaderModel.FEEDBACK_BUTTON_CALLBACK, mDelegate::onFeedbackButtonClicked);
}
private void createBottomSheetContents() {
mContent =
new AssistantBottomSheetContent(mContext, () -> new AssistantBottomBarDelegate() {
@Override
......@@ -103,29 +107,27 @@ public class AssistantTriggerScript {
// Allow swipe-to-dismiss.
mContent.setPeekModeDisabled(true);
mHeaderModel = new AssistantHeaderModel();
mHeaderModel.set(
AssistantHeaderModel.FEEDBACK_BUTTON_CALLBACK, mDelegate::onFeedbackButtonClicked);
mHeaderCoordinator = new AssistantHeaderCoordinator(context, mHeaderModel);
mChipsContainer = new LinearLayout(context);
if (mHeaderCoordinator != null) {
mHeaderCoordinator.destroy();
}
mHeaderCoordinator = new AssistantHeaderCoordinator(mContext, mHeaderModel);
mChipsContainer = new LinearLayout(mContext);
mChipsContainer.setOrientation(LinearLayout.HORIZONTAL);
int horizontalMargin = context.getResources().getDimensionPixelSize(
int horizontalMargin = mContext.getResources().getDimensionPixelSize(
R.dimen.autofill_assistant_bottombar_horizontal_spacing);
int verticalMargin = AssistantDimension.getPixelSizeDp(context, 16);
int verticalMargin = AssistantDimension.getPixelSizeDp(mContext, 16);
mChipsContainer.setPadding(
horizontalMargin, verticalMargin, horizontalMargin, verticalMargin);
mInnerChipSpacing = mContext.getResources().getDimensionPixelSize(
R.dimen.autofill_assistant_actions_spacing);
mRootViewContainer = (AssistantRootViewContainer) LayoutInflater.from(context).inflate(
R.layout.autofill_assistant_bottom_sheet_content, /* root= */ null);
mScrollableContent = mRootViewContainer.findViewById(R.id.scrollable_content);
mRootViewContainer.addView(mHeaderCoordinator.getView(), 0);
mRootViewContainer.addView(mChipsContainer,
AssistantRootViewContainer rootViewContainer =
(AssistantRootViewContainer) LayoutInflater.from(mContext).inflate(
R.layout.autofill_assistant_bottom_sheet_content, /* root= */ null);
ScrollView scrollableContent = rootViewContainer.findViewById(R.id.scrollable_content);
rootViewContainer.addView(mHeaderCoordinator.getView(), 0);
rootViewContainer.addView(mChipsContainer,
new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
mContent.setContent(mRootViewContainer, mScrollableContent);
mContent.setContent(rootViewContainer, scrollableContent);
}
public void destroy() {
......@@ -173,13 +175,13 @@ public class AssistantTriggerScript {
private void bindChips(List<AssistantChip> chips, int[] actions) {
assert chips.size() == actions.length;
for (int i = 0; i < chips.size(); ++i) {
int action = actions[i];
if (action == TriggerScriptAction.SHOW_CANCEL_POPUP) {
chips.get(i).setPopupItems(mCancelPopupItems,
int index = i;
if (actions[index] == TriggerScriptAction.SHOW_CANCEL_POPUP) {
chips.get(index).setPopupItems(mCancelPopupItems,
result -> mDelegate.onTriggerScriptAction(mCancelPopupActions.get(result)));
} else {
chips.get(i).setSelectedListener(
() -> mDelegate.onTriggerScriptAction(actions[action]));
chips.get(index).setSelectedListener(
() -> mDelegate.onTriggerScriptAction(actions[index]));
}
}
}
......@@ -218,6 +220,7 @@ public class AssistantTriggerScript {
}
public void show() {
createBottomSheetContents();
update();
mBottomSheetController.removeObserver(mBottomSheetObserver);
mBottomSheetController.addObserver(mBottomSheetObserver);
......
......@@ -12,6 +12,7 @@ import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.chrome.browser.autofill_assistant.AutofillAssistantClient;
import org.chromium.chrome.browser.autofill_assistant.AutofillAssistantPreferencesUtil;
import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChip;
import org.chromium.chrome.browser.autofill_assistant.header.AssistantHeaderModel;
import org.chromium.chrome.browser.autofill_assistant.metrics.LiteScriptFinishedState;
......@@ -98,6 +99,9 @@ public class AssistantTriggerScriptBridge {
mTriggerScript.setLeftAlignedChips(leftAlignedChips, leftAlignedChipsActions);
mTriggerScript.setRightAlignedChips(rightAlignedChips, rightAlignedChipsActions);
mTriggerScript.show();
// A trigger script was displayed, users are no longer considered first-time users.
AutofillAssistantPreferencesUtil.setAutofillAssistantReturningLiteScriptUser();
}
@CalledByNative
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.autofill_assistant;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.RootMatchers.withDecorView;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withClassName;
import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.core.StringContains.containsString;
import static org.mockito.Mockito.verify;
import android.support.test.InstrumentationRegistry;
import android.view.Gravity;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.test.filters.MediumTest;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.chrome.autofill_assistant.R;
import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChip;
import org.chromium.chrome.browser.autofill_assistant.drawable.AssistantDrawableIcon;
import org.chromium.chrome.browser.autofill_assistant.generic_ui.AssistantDrawable;
import org.chromium.chrome.browser.autofill_assistant.header.AssistantHeaderModel;
import org.chromium.chrome.browser.autofill_assistant.trigger_scripts.AssistantTriggerScript;
import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import java.util.Arrays;
import java.util.List;
/** UI tests for {@code AssistantTriggerScript}. */
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
@RunWith(ChromeJUnit4ClassRunner.class)
public class AutofillAssistantTriggerScriptTest {
private static final String TEST_PAGE = "/components/test/data/autofill_assistant/html/"
+ "autofill_assistant_target_website.html";
@Mock
Runnable mRunnableMockCancelSession;
@Mock
Runnable mRunnableMockCancelForever;
@Rule
public MockitoRule mMockitoRule = MockitoJUnit.rule();
@Rule
public CustomTabActivityTestRule mTestRule = new CustomTabActivityTestRule();
@Before
public void setUp() {
mTestRule.startCustomTabActivityWithIntent(CustomTabsTestUtils.createMinimalCustomTabIntent(
InstrumentationRegistry.getTargetContext(),
mTestRule.getTestServer().getURL(TEST_PAGE)));
}
protected BottomSheetController getBottomSheetController() {
return AutofillAssistantUiTestUtil.getBottomSheetController(mTestRule.getActivity());
}
/**
* Creates a linear layout at the bottom of the screen for use in tests. Showing content
* directly in the bottom sheet has been flaky in the past (see e.g., crbug.com/1146084).
*/
private LinearLayout createViewContainerForTest() {
CoordinatorLayout.LayoutParams lp = new CoordinatorLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.BOTTOM;
LinearLayout container = new LinearLayout(mTestRule.getActivity());
container.setOrientation(LinearLayout.VERTICAL);
ViewGroup chromeCoordinatorView = mTestRule.getActivity().findViewById(R.id.coordinator);
chromeCoordinatorView.addView(container, lp);
return container;
}
@Test
@MediumTest
public void testTriggerScript() throws Exception {
AssistantTriggerScript triggerScript = TestThreadUtils.runOnUiThreadBlocking(
()
-> new AssistantTriggerScript(
mTestRule.getActivity(), new AssistantTriggerScript.Delegate() {
@Override
public void onTriggerScriptAction(int action) {}
@Override
public void onBottomSheetClosedWithSwipe() {}
@Override
public void onBackButtonPressed() {}
@Override
public void onFeedbackButtonClicked() {}
}, getBottomSheetController()));
TestThreadUtils.runOnUiThreadBlocking(() -> {
AssistantHeaderModel headerModel = triggerScript.getHeaderModel();
headerModel.set(AssistantHeaderModel.DISABLE_ANIMATIONS_FOR_TESTING, true);
headerModel.set(AssistantHeaderModel.STATUS_MESSAGE, "Hello world!");
headerModel.set(AssistantHeaderModel.USE_STEP_PROGRESS_BAR, true);
headerModel.set(AssistantHeaderModel.STEP_PROGRESS_BAR_ICONS,
Arrays.asList(AssistantDrawable.createFromIcon(
AssistantDrawableIcon.PROGRESSBAR_DEFAULT_INITIAL_STEP),
AssistantDrawable.createFromIcon(
AssistantDrawableIcon.PROGRESSBAR_DEFAULT_DATA_COLLECTION),
AssistantDrawable.createFromIcon(
AssistantDrawableIcon.PROGRESSBAR_DEFAULT_PAYMENT),
AssistantDrawable.createFromIcon(
AssistantDrawableIcon.PROGRESSBAR_DEFAULT_FINAL_STEP)));
headerModel.set(AssistantHeaderModel.PROGRESS_ACTIVE_STEP, 1);
List<AssistantChip> leftAlignedChips = triggerScript.getLeftAlignedChipsForTest();
leftAlignedChips.add(new AssistantChip(AssistantChip.Type.BUTTON_HAIRLINE,
AssistantChip.Icon.OVERFLOW, "", false, false, true, () -> {}));
leftAlignedChips.get(0).setPopupItems(
Arrays.asList("Not for this session", "Never show again"), result -> {
if (result == 0) {
mRunnableMockCancelSession.run();
} else if (result == 1) {
mRunnableMockCancelForever.run();
}
});
List<AssistantChip> rightAlignedChips = triggerScript.getRightAlignedChipsForTest();
rightAlignedChips.add(new AssistantChip(AssistantChip.Type.BUTTON_HAIRLINE,
AssistantChip.Icon.NONE, "Not now", false, false, true, () -> {}));
rightAlignedChips.add(new AssistantChip(AssistantChip.Type.BUTTON_FILLED_BLUE,
AssistantChip.Icon.NONE, "Fast checkout", false, false, true, () -> {}));
});
triggerScript.disableBottomSheetAnimationsForTesting(true);
TestThreadUtils.runOnUiThreadBlocking(() -> {
triggerScript.update();
createViewContainerForTest().addView(
triggerScript.getBottomSheetContentForTest().getContentView());
});
onView(withId(R.id.autofill_assistant)).check(matches(isDisplayed()));
onView(withId(R.id.header)).check(matches(isDisplayed()));
onView(withId(R.id.poodle_wrapper)).check(matches(isDisplayed()));
onView(withText("Hello world!")).check(matches(isDisplayed()));
onView(withId(R.id.profile_image)).check(matches(isDisplayed()));
onView(withId(R.id.step_progress_bar)).check(matches(isDisplayed()));
onView(withContentDescription(R.string.autofill_assistant_overflow_options))
.check(matches(isDisplayed()));
onView(withText("Not now")).check(matches(isDisplayed()));
onView(withText("Fast checkout")).check(matches(isDisplayed()));
onView(withContentDescription(R.string.autofill_assistant_overflow_options))
.perform(click());
onView(withText("Not for this session"))
.inRoot(withDecorView(withClassName(containsString("Popup"))))
.perform(click());
verify(mRunnableMockCancelSession).run();
onView(withContentDescription(R.string.autofill_assistant_overflow_options))
.perform(click());
onView(withText("Never show again"))
.inRoot(withDecorView(withClassName(containsString("Popup"))))
.perform(click());
verify(mRunnableMockCancelForever).run();
}
}
......@@ -9,7 +9,7 @@ import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
/** Autofill Assistant related preferences util class. */
class AutofillAssistantPreferencesUtil {
public class AutofillAssistantPreferencesUtil {
/**
* If a user explicitly cancels a lite script >= this number, they will implicitly opt-out of
* this experience and never see a lite script again. Note: this is only temporarily in place
......@@ -43,7 +43,7 @@ class AutofillAssistantPreferencesUtil {
}
/** Marks a user as having seen a lite script at least once before. */
static void setAutofillAssistantReturningLiteScriptUser() {
public static void setAutofillAssistantReturningLiteScriptUser() {
SharedPreferencesManager.getInstance().writeBoolean(
ChromePreferenceKeys.AUTOFILL_ASSISTANT_FIRST_TIME_LITE_SCRIPT_USER, false);
}
......
......@@ -3289,7 +3289,8 @@ static_library("browser") {
]
deps += [ "//chrome/android/modules/dev_ui/provider:native" ]
}
} else { #!is_android
} else {
#!is_android
sources += [
"accessibility/caption_controller.cc",
"accessibility/caption_controller.h",
......@@ -4101,7 +4102,7 @@ static_library("browser") {
"task_manager/sampling/shared_sampler_posix.cc",
]
# TODO(crbug.com/1052397): Rename chromeos_is_browser_only to is_lacros.
# TODO(crbug.com / 1052397): Rename chromeos_is_browser_only to is_lacros.
if (!chromeos_is_browser_only) {
sources += [ "first_run/first_run_internal_posix.cc" ]
}
......@@ -5617,7 +5618,7 @@ static_library("browser") {
"//components/guest_view/browser",
"//media/cast:sender",
# TODO(crbug.com/879012): mirroring shouldn't depend on enable_extensions.
# TODO(crbug.com / 879012): mirroring shouldn't depend on enable_extensions.
"//components/mirroring/browser",
"//components/mirroring/mojom:host",
"//components/mirroring/mojom:service",
......@@ -6307,7 +6308,7 @@ proto_library("permissions_proto") {
}
grit("resources") {
# TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
# TODO(crbug.com / 1112471): Get this to run cleanly under Python 3.
run_under_python2 = true
source = "browser_resources.grd"
......
......@@ -52,6 +52,10 @@ void DynamicTriggerConditions::AddSelectorsFromTriggerScript(
ExtractSelectors(proto.trigger_condition(), &selectors_);
}
void DynamicTriggerConditions::ClearSelectors() {
selectors_.clear();
}
base::Optional<bool> DynamicTriggerConditions::GetSelectorMatches(
const Selector& selector) const {
auto it = selector_matches_.find(selector);
......
......@@ -28,6 +28,9 @@ class DynamicTriggerConditions {
// selectors to be queried in |Update|.
virtual void AddSelectorsFromTriggerScript(const TriggerScriptProto& proto);
// Clears all selectors from the list of selectors to be queried in |Update|.
virtual void ClearSelectors();
// Returns whether |selector| currently matches the DOM tree. |Update| must
// be called prior to this method. Only selectors that have previously been
// added via |AddSelectorsFromTriggerScript| can be queried.
......
......@@ -115,4 +115,13 @@ TEST_F(DynamicTriggerConditionsTest, Update) {
base::make_optional(true));
}
TEST_F(DynamicTriggerConditionsTest, ClearSelectors) {
TriggerScriptProto proto;
*proto.mutable_trigger_condition()->mutable_selector() = ToSelectorProto("a");
dynamic_trigger_conditions_.AddSelectorsFromTriggerScript(proto);
EXPECT_EQ(GetSelectorsForTest()->size(), 1u);
dynamic_trigger_conditions_.ClearSelectors();
EXPECT_EQ(GetSelectorsForTest()->size(), 0u);
}
} // namespace autofill_assistant
......@@ -25,6 +25,10 @@ class MockDynamicTriggerConditions : public DynamicTriggerConditions {
MOCK_METHOD2(OnUpdate,
void(WebController* web_controller,
base::OnceCallback<void(void)>& callback));
MOCK_METHOD1(AddSelectorsFromTriggerScript,
void(const TriggerScriptProto& proto));
MOCK_METHOD0(ClearSelectors, void(void));
};
} // namespace autofill_assistant
......
......@@ -9,6 +9,7 @@
#include "components/autofill_assistant/browser/client_context.h"
#include "components/autofill_assistant/browser/protocol_utils.h"
#include "components/autofill_assistant/browser/url_utils.h"
#include "components/ukm/content/source_url_recorder.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
......@@ -239,6 +240,11 @@ void TriggerScriptCoordinator::WebContentsDestroyed() {
void TriggerScriptCoordinator::StartCheckingTriggerConditions() {
is_checking_trigger_conditions_ = true;
dynamic_trigger_conditions_->ClearSelectors();
for (const auto& trigger_script : trigger_scripts_) {
dynamic_trigger_conditions_->AddSelectorsFromTriggerScript(
trigger_script->AsProto());
}
static_trigger_conditions_->Init(
client_, deeplink_url_, trigger_context_.get(),
base::BindOnce(&TriggerScriptCoordinator::CheckDynamicTriggerConditions,
......
......@@ -220,6 +220,10 @@ TEST_F(TriggerScriptCoordinatorTest, StartChecksStaticAndDynamicConditions) {
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
EXPECT_CALL(*mock_static_trigger_conditions_, Init)
.WillOnce(RunOnceCallback<3>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_, ClearSelectors).Times(1);
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
AddSelectorsFromTriggerScript(response.trigger_scripts(0)))
.Times(1);
ON_CALL(*mock_dynamic_trigger_conditions_, OnUpdate(mock_web_controller_, _))
.WillByDefault(RunOnceCallback<1>());
ON_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
......
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