Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Unified Diff: ios/chrome/browser/ui/contextual_search/touch_to_search_permissions_mediator_unittest.mm

Issue 2588713002: Upstream Chrome on iOS source code [4/11]. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ios/chrome/browser/ui/contextual_search/touch_to_search_permissions_mediator_unittest.mm
diff --git a/ios/chrome/browser/ui/contextual_search/touch_to_search_permissions_mediator_unittest.mm b/ios/chrome/browser/ui/contextual_search/touch_to_search_permissions_mediator_unittest.mm
new file mode 100644
index 0000000000000000000000000000000000000000..aebc8fbd87d9ca977327eea0fa7cb57f0c888b20
--- /dev/null
+++ b/ios/chrome/browser/ui/contextual_search/touch_to_search_permissions_mediator_unittest.mm
@@ -0,0 +1,633 @@
+// Copyright 2016 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.
+
+#import "ios/chrome/browser/ui/contextual_search/touch_to_search_permissions_mediator.h"
+
+#include <UIKit/UIKit.h>
+#include <memory>
+
+#include "base/command_line.h"
+#import "base/mac/scoped_nsobject.h"
+#include "base/memory/ptr_util.h"
+#include "base/metrics/field_trial.h"
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#import "base/test/ios/wait_util.h"
+#include "base/time/time.h"
+#include "components/prefs/pref_service.h"
+#include "components/search_engines/template_url.h"
+#include "components/search_engines/template_url_data.h"
+#include "components/search_engines/template_url_service.h"
+#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
+#include "ios/chrome/browser/chrome_switches.h"
+#include "ios/chrome/browser/pref_names.h"
+#include "ios/chrome/browser/search_engines/template_url_service_factory.h"
+#include "ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.h"
+#include "ios/chrome/browser/sync/ios_chrome_profile_sync_test_util.h"
+#include "ios/chrome/browser/sync/sync_setup_service_factory.h"
+#include "ios/chrome/browser/sync/sync_setup_service_mock.h"
+#import "ios/chrome/browser/ui/contextual_search/touch_to_search_permissions_mediator+testing.h"
+#include "ios/web/public/test/test_web_thread_bundle.h"
+#include "net/base/network_change_notifier.h"
+#import "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+#import "third_party/ocmock/OCMock/OCMock.h"
+#include "third_party/ocmock/gtest_support.h"
+
+using testing::Return;
+
+@interface TestTouchToSearchPermissionsAudience
+ : NSObject<TouchToSearchPermissionsChangeAudience>
+@property BOOL updated;
+@end
+
+@implementation TestTouchToSearchPermissionsAudience
+@synthesize updated = _updated;
+- (void)touchToSearchPermissionsUpdated {
+ self.updated = YES;
+}
+@end
+
+namespace {
+
+std::unique_ptr<KeyedService> CreateSyncSetupService(
+ web::BrowserState* context) {
+ ios::ChromeBrowserState* chrome_browser_state =
+ ios::ChromeBrowserState::FromBrowserState(context);
+ syncer::SyncService* sync_service =
+ IOSChromeProfileSyncServiceFactory::GetForBrowserState(
+ chrome_browser_state);
+ return base::MakeUnique<SyncSetupServiceMock>(
+ sync_service, chrome_browser_state->GetPrefs());
+}
+
+// Override NetworkChangeNotifier to simulate connection type changes for tests.
+class TestNetworkChangeNotifier : public net::NetworkChangeNotifier {
+ public:
+ TestNetworkChangeNotifier()
+ : net::NetworkChangeNotifier(),
+ connection_type_to_return_(
+ net::NetworkChangeNotifier::CONNECTION_UNKNOWN) {}
+
+ // Simulates a change of the connection type to |type|. This will notify any
+ // objects that are NetworkChangeNotifiers.
+ void SimulateNetworkConnectionChange(
+ net::NetworkChangeNotifier::ConnectionType type) {
+ connection_type_to_return_ = type;
+ net::NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ private:
+ ConnectionType GetCurrentConnectionType() const override {
+ return connection_type_to_return_;
+ }
+
+ // The currently simulated network connection type. If this is set to
+ // CONNECTION_NONE, then NetworkChangeNotifier::IsOffline will return true.
+ net::NetworkChangeNotifier::ConnectionType connection_type_to_return_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestNetworkChangeNotifier);
+};
+
+class TouchToSearchPermissionsMediatorTest : public PlatformTest {
+ protected:
+ TouchToSearchPermissionsMediatorTest() {
+ TestChromeBrowserState::Builder browserStateBuilder;
+ browserStateBuilder.AddTestingFactory(
+ SyncSetupServiceFactory::GetInstance(), &CreateSyncSetupService);
+ browserStateBuilder.AddTestingFactory(
+ ios::TemplateURLServiceFactory::GetInstance(),
+ ios::TemplateURLServiceFactory::GetDefaultFactory());
+ browser_state_ = browserStateBuilder.Build();
+ template_url_service_ =
+ ios::TemplateURLServiceFactory::GetForBrowserState(BrowserState());
+ template_url_service_->Load();
+ tts_permissions_.reset([[TouchToSearchPermissionsMediator alloc]
+ initWithBrowserState:BrowserState()]);
+ }
+
+ ios::ChromeBrowserState* BrowserState() { return browser_state_.get(); }
+
+ web::TestWebThreadBundle thread_bundle_;
+ std::unique_ptr<TestChromeBrowserState> browser_state_;
+ base::scoped_nsobject<TouchToSearchPermissionsMediator> tts_permissions_;
+ TemplateURLService* template_url_service_;
+};
+
+TEST_F(TouchToSearchPermissionsMediatorTest, PrefStates) {
+ // Expect empty browser state to have undecided pref value.
+ EXPECT_EQ(TouchToSearch::UNDECIDED, [tts_permissions_ preferenceState]);
+
+ const struct {
+ const std::string pref_value;
+ TouchToSearch::TouchToSearchPreferenceState state;
+ } tests[] = {
+ {"false", TouchToSearch::DISABLED},
+ {"true", TouchToSearch::ENABLED},
+ {"", TouchToSearch::UNDECIDED},
+ };
+
+ for (const auto& test : tests) {
+ // set state, test value
+ BrowserState()->GetPrefs()->SetString(prefs::kContextualSearchEnabled,
+ test.pref_value);
+ EXPECT_EQ(test.state, [tts_permissions_ preferenceState]);
+ // set state from value
+ [tts_permissions_ setPreferenceState:test.state];
+ std::string prefValue =
+ BrowserState()->GetPrefs()->GetString(prefs::kContextualSearchEnabled);
+ EXPECT_EQ(test.pref_value, prefValue);
+ }
+
+// For non-debug builds, also test cases that would DCHECK.
+#if !DCHECK_IS_ON()
+ // Check that an unexpected pref value returns DISABLED.
+ BrowserState()->GetPrefs()->SetString(prefs::kContextualSearchEnabled,
+ "somethingElse");
+ EXPECT_EQ(TouchToSearch::DISABLED, [tts_permissions_ preferenceState]);
+#endif
+}
+
+TEST_F(TouchToSearchPermissionsMediatorTest, TapContext) {
+ const GURL secure_url("https://www.some-website.com/");
+ const GURL insecure_url("http://www.some-website.com/");
+ const struct {
+ TouchToSearch::TouchToSearchPreferenceState state;
+ const GURL* url;
+ BOOL expected_permission;
+ } tests[] = {
+ // DISABLED should always deny extraction.
+ // ENABLED should permit it.
+ // UNDECIDED should permit it only on http pages.
+ {TouchToSearch::DISABLED, &secure_url, NO},
+ {TouchToSearch::DISABLED, &insecure_url, NO},
+ {TouchToSearch::ENABLED, &secure_url, YES},
+ {TouchToSearch::ENABLED, &insecure_url, YES},
+ {TouchToSearch::UNDECIDED, &secure_url, NO},
+ {TouchToSearch::UNDECIDED, &insecure_url, YES},
+ };
+
+ for (const auto& test : tests) {
+ [tts_permissions_ setPreferenceState:test.state];
+ EXPECT_EQ(test.expected_permission,
+ [tts_permissions_ canExtractTapContextForURL:*test.url]);
+ }
+}
+
+TEST_F(TouchToSearchPermissionsMediatorTest, URLSending) {
+ // Wrap the tests of -canSendPageURLs states in contexts of the different
+ // pref states; DISABLED should mean that the expected result is false
+ // regardless of other tests.
+ const struct {
+ TouchToSearch::TouchToSearchPreferenceState prefState;
+ BOOL performs_check;
+ } state_contexts[] = {
+ {TouchToSearch::DISABLED, NO},
+ {TouchToSearch::UNDECIDED, YES},
+ {TouchToSearch::ENABLED, YES},
+ };
+
+ const struct {
+ bool sync_enabled;
+ BOOL expected_permission;
+ } tests[] = {
+ {false, NO}, {true, YES},
+ };
+
+ for (const auto& context : state_contexts) {
+ [tts_permissions_ setPreferenceState:context.prefState];
+ for (const auto& test : tests) {
+ SyncSetupServiceMock* syncSetupService =
+ static_cast<SyncSetupServiceMock*>(
+ SyncSetupServiceFactory::GetForBrowserState(BrowserState()));
+ if (context.performs_check) {
+ EXPECT_CALL(*syncSetupService, IsSyncEnabled())
+ .WillOnce(Return(test.sync_enabled));
+ }
+ EXPECT_EQ(test.expected_permission && context.performs_check,
+ [tts_permissions_ canSendPageURLs]);
+ }
+ }
+}
+
+TEST_F(TouchToSearchPermissionsMediatorTest, SearchPreloading) {
+ TestNetworkChangeNotifier network_change_notifier;
+
+ const struct {
+ TouchToSearch::TouchToSearchPreferenceState prefState;
+ BOOL expectation_mask;
+ } state_contexts[] = {
+ {TouchToSearch::DISABLED, NO},
+ {TouchToSearch::UNDECIDED, YES},
+ {TouchToSearch::ENABLED, YES},
+ };
+
+ const struct {
+ bool prefetch_enabled;
+ bool wifi_prefetch_only;
+ net::NetworkChangeNotifier::ConnectionType network_connection_type;
+ BOOL expected_permission;
+ } tests[] = {
+ // clang-format off
+ // If prefectching is off, network preloading should never be allowed.
+ {false, false, net::NetworkChangeNotifier::CONNECTION_WIFI, NO},
+ {false, false, net::NetworkChangeNotifier::CONNECTION_3G, NO},
+ {false, true, net::NetworkChangeNotifier::CONNECTION_WIFI, NO},
+ {false, true, net::NetworkChangeNotifier::CONNECTION_3G, NO},
+
+ // If prefetching is on and not wifi-only, preloading should always be OK.
+ {true, false, net::NetworkChangeNotifier::CONNECTION_WIFI, YES},
+ {true, false, net::NetworkChangeNotifier::CONNECTION_3G, YES},
+
+ // Wifi only prefetching should not allow prefetch over cellular.
+ {true, true, net::NetworkChangeNotifier::CONNECTION_WIFI, YES},
+ {true, true, net::NetworkChangeNotifier::CONNECTION_3G, NO},
+
+ // clang-format on
+ };
+
+ for (const auto& context : state_contexts) {
+ [tts_permissions_ setPreferenceState:context.prefState];
+ for (const auto& test : tests) {
+ BrowserState()->GetPrefs()->SetBoolean(prefs::kNetworkPredictionEnabled,
+ test.prefetch_enabled);
+ BrowserState()->GetPrefs()->SetBoolean(prefs::kNetworkPredictionWifiOnly,
+ test.wifi_prefetch_only);
+ network_change_notifier.SimulateNetworkConnectionChange(
+ test.network_connection_type);
+ EXPECT_EQ(test.expected_permission && context.expectation_mask,
+ [tts_permissions_ canPreloadSearchResults]);
+ }
+ }
+}
+
+TEST_F(TouchToSearchPermissionsMediatorTest,
+ AreQueriesDisallowedWithoutTemplateService) {
+ TestChromeBrowserState::Builder browserStateBuilder;
+ std::unique_ptr<TestChromeBrowserState> browser_state(
+ browserStateBuilder.Build());
+ base::scoped_nsobject<TouchToSearchPermissionsMediator> tts_permissions(
+ [[TouchToSearchPermissionsMediator alloc]
+ initWithBrowserState:browser_state.get()]);
+ EXPECT_FALSE([tts_permissions areContextualSearchQueriesSupported]);
+}
+
+TEST_F(TouchToSearchPermissionsMediatorTest, AreQueriesAllowed) {
+ // The initial default search engine should support contextual search.
+ EXPECT_TRUE([tts_permissions_ areContextualSearchQueriesSupported]);
+
+ // Make a user-defined search engine and set it as the default.
+ TemplateURLData data;
+ data.SetShortName(base::ASCIIToUTF16("cs-not-supported"));
+
+ TemplateURL* newUrl = template_url_service_->Add(
+ std::unique_ptr<TemplateURL>(new TemplateURL(data)));
+ // |template_url_service_| will take ownership of newUrl
+ ASSERT_TRUE(newUrl);
+ template_url_service_->SetUserSelectedDefaultSearchProvider(newUrl);
+
+ // The newly-selected search engine doesn't support contextual search.
+ EXPECT_FALSE([tts_permissions_ areContextualSearchQueriesSupported]);
+}
+
+TEST_F(TouchToSearchPermissionsMediatorTest, CanEnable) {
+ base::scoped_nsobject<MockTouchToSearchPermissionsMediator> permissions(
+ [[MockTouchToSearchPermissionsMediator alloc]
+ initWithBrowserState:BrowserState()]);
+
+ const struct {
+ BOOL enabled_on_device;
+ TouchToSearch::TouchToSearchPreferenceState prefState;
+ BOOL voiceover_enabled;
+ BOOL queries_allowed;
+ BOOL expect_available;
+ } tests[] = {
+ // clang-format off
+ // Enabled cases:
+ // Enabled on command line, voiceover off, queries supported,
+ // preference state not disabled.
+ {YES, TouchToSearch::ENABLED, NO, YES, YES},
+ {YES, TouchToSearch::UNDECIDED, NO, YES, YES},
+
+ // Disabled cases: All others.
+ {NO, TouchToSearch::DISABLED, NO, NO, NO},
+ {NO, TouchToSearch::DISABLED, NO, YES, NO},
+ {NO, TouchToSearch::DISABLED, YES, NO, NO},
+ {NO, TouchToSearch::DISABLED, YES, YES, NO},
+ {NO, TouchToSearch::UNDECIDED, NO, NO, NO},
+ {NO, TouchToSearch::UNDECIDED, NO, YES, NO},
+ {NO, TouchToSearch::UNDECIDED, YES, NO, NO},
+ {NO, TouchToSearch::UNDECIDED, YES, YES, NO},
+ {NO, TouchToSearch::ENABLED, NO, NO, NO},
+ {NO, TouchToSearch::ENABLED, NO, YES, NO},
+ {NO, TouchToSearch::ENABLED, YES, NO, NO},
+ {NO, TouchToSearch::ENABLED, YES, YES, NO},
+ {YES, TouchToSearch::DISABLED, NO, NO, NO},
+ {YES, TouchToSearch::DISABLED, NO, YES, NO},
+ {YES, TouchToSearch::DISABLED, YES, NO, NO},
+ {YES, TouchToSearch::DISABLED, YES, YES, NO},
+ {YES, TouchToSearch::UNDECIDED, NO, NO, NO},
+ {YES, TouchToSearch::UNDECIDED, YES, NO, NO},
+ {YES, TouchToSearch::UNDECIDED, YES, YES, NO},
+ {YES, TouchToSearch::ENABLED, NO, NO, NO},
+ {YES, TouchToSearch::ENABLED, YES, NO, NO},
+ {YES, TouchToSearch::ENABLED, YES, YES, NO},
+ // clang-format on
+ };
+
+ for (const auto& test : tests) {
+ [[permissions class]
+ setIsTouchToSearchAvailableOnDevice:test.enabled_on_device];
+ permissions.get().preferenceState = test.prefState;
+ permissions.get().isVoiceOverEnabled = test.voiceover_enabled;
+ permissions.get().areContextualSearchQueriesSupported =
+ test.queries_allowed;
+ EXPECT_EQ(test.expect_available, [permissions canEnable]);
+ }
+}
+
+TEST_F(TouchToSearchPermissionsMediatorTest, AudienceNotifications) {
+ base::scoped_nsobject<id> audience(
+ [[TestTouchToSearchPermissionsAudience alloc] init]);
+ [tts_permissions_ setAudience:audience];
+ base::TimeDelta delay = base::TimeDelta::FromMilliseconds(50);
+ [[NSNotificationCenter defaultCenter]
+ postNotificationName:UIApplicationWillEnterForegroundNotification
+ object:[UIApplication sharedApplication]];
+ // Audience call is asynchronous, so expect nothing yet.
+ EXPECT_FALSE([audience updated]);
+ // Wait for async call.
+ base::test::ios::WaitUntilCondition(
+ ^bool(void) {
+ return [audience updated];
+ },
+ nullptr, delay);
+ EXPECT_TRUE([audience updated]);
+ // Reset |audience|.
+ [audience setUpdated:NO];
+
+ [[NSNotificationCenter defaultCenter]
+ postNotificationName:UIAccessibilityVoiceOverStatusChanged
+ object:nil];
+ // Audience call is asynchronous, so expect nothing yet.
+ EXPECT_FALSE([audience updated]);
+ // Wait for async call.
+ base::test::ios::WaitUntilCondition(^bool(void) {
+ return [audience updated];
+ });
+ EXPECT_TRUE([audience updated]);
+ // Reset |audience|.
+ [audience setUpdated:NO];
+
+ BrowserState()->GetPrefs()->SetString(prefs::kContextualSearchEnabled,
+ "true");
+ // Audience call is asynchronous, so expect nothing yet.
+ EXPECT_FALSE([audience updated]);
+ // Wait for async call.
+ base::test::ios::WaitUntilCondition(^bool(void) {
+ return [audience updated];
+ });
+ EXPECT_TRUE([audience updated]);
+ // Reset |audience|.
+ [audience setUpdated:NO];
+
+ // Make a user-defined search engine and set it as the default. This should
+ // trigger a prefs update that will in turn trigger an audience notification.
+ TemplateURLData data;
+ data.SetShortName(base::ASCIIToUTF16("cs-not-supported"));
+ TemplateURL* newUrl = template_url_service_->Add(
+ std::unique_ptr<TemplateURL>(new TemplateURL(data)));
+
+ // |template_url_service_| will take ownership of newUrl
+ ASSERT_TRUE(newUrl);
+ template_url_service_->SetUserSelectedDefaultSearchProvider(newUrl);
+ // Audience call is asynchronous, so expect nothing yet.
+ EXPECT_FALSE([audience updated]);
+ // Wait for async call.
+ base::test::ios::WaitUntilCondition(
+ ^bool(void) {
+ return [audience updated];
+ },
+ nullptr, delay);
+ EXPECT_TRUE([audience updated]);
+ // Reset |audience|.
+ [audience setUpdated:NO];
+
+ // Once set to nil, audience shouldn't be notified.
+ [tts_permissions_ setAudience:nil];
+ [[NSNotificationCenter defaultCenter]
+ postNotificationName:UIAccessibilityVoiceOverStatusChanged
+ object:nil];
+ BrowserState()->GetPrefs()->SetString(prefs::kContextualSearchEnabled,
+ "true");
+ // Audience call is asynchronous, so expect nothing yet.
+ EXPECT_FALSE([audience updated]);
+ // Wait long enough for async call not to occur.
+ base::test::ios::SpinRunLoopWithMaxDelay(delay);
+ EXPECT_FALSE([audience updated]);
+ // Reset |audience|.
+ [audience setUpdated:NO];
+
+ base::scoped_nsobject<id> audience2(
+ [[TestTouchToSearchPermissionsAudience alloc] init]);
+ // If the permissions object is destroyed, queued notifications should still
+ // be sent.
+ [tts_permissions_ setAudience:audience2];
+ [[NSNotificationCenter defaultCenter]
+ postNotificationName:UIAccessibilityVoiceOverStatusChanged
+ object:nil];
+ tts_permissions_.reset();
+ base::test::ios::WaitUntilCondition(
+ ^bool(void) {
+ return [audience2 updated];
+ },
+ nullptr, delay);
+ EXPECT_TRUE([audience2 updated]);
+}
+
+TEST_F(TouchToSearchPermissionsMediatorTest, AudiencePrefsSynchronous) {
+ id audience = [OCMockObject
+ niceMockForProtocol:@protocol(TouchToSearchPermissionsChangeAudience)];
+ [tts_permissions_ setAudience:audience];
+
+ // Test that setting preferences through the same permissions object triggers
+ // audience methods.
+ [[audience expect]
+ touchToSearchDidChangePreferenceState:TouchToSearch::ENABLED];
+ [tts_permissions_ setPreferenceState:TouchToSearch::ENABLED];
+ EXPECT_OCMOCK_VERIFY(audience);
+ [tts_permissions_ setPreferenceState:TouchToSearch::DISABLED];
+
+ // Test that setting preferences through another permissions object triggers
+ // audience methods.
+ base::scoped_nsobject<TouchToSearchPermissionsMediator> other_permissions(
+ [[TouchToSearchPermissionsMediator alloc]
+ initWithBrowserState:BrowserState()]);
+ [[audience expect]
+ touchToSearchDidChangePreferenceState:TouchToSearch::ENABLED];
+ [other_permissions setPreferenceState:TouchToSearch::ENABLED];
+ EXPECT_OCMOCK_VERIFY(audience);
+ [tts_permissions_ setPreferenceState:TouchToSearch::DISABLED];
+
+ // Test that setting preferences through the prefs system triggers audience
+ // methods.
+ [[audience expect]
+ touchToSearchDidChangePreferenceState:TouchToSearch::ENABLED];
+ BrowserState()->GetPrefs()->SetString(prefs::kContextualSearchEnabled,
+ "true");
+ EXPECT_OCMOCK_VERIFY(audience);
+}
+
+TEST_F(TouchToSearchPermissionsMediatorTest, OTR) {
+ ios::ChromeBrowserState* otr_state =
+ BrowserState()->GetOffTheRecordChromeBrowserState();
+ base::scoped_nsobject<TouchToSearchPermissionsMediator> permissions([
+ [TouchToSearchPermissionsMediator alloc] initWithBrowserState:otr_state]);
+
+ EXPECT_FALSE([permissions canEnable]);
+ EXPECT_FALSE([permissions canSendPageURLs]);
+ EXPECT_FALSE([permissions canEnable]);
+ EXPECT_FALSE([permissions canPreloadSearchResults]);
+ EXPECT_EQ(TouchToSearch::DISABLED, [permissions preferenceState]);
+
+ otr_state->GetPrefs()->SetString(prefs::kContextualSearchEnabled, "true");
+ EXPECT_EQ(TouchToSearch::DISABLED, [permissions preferenceState]);
+ EXPECT_FALSE([permissions canEnable]);
+
+ EXPECT_EQ(nil, [permissions audience]);
+ id audience = [OCMockObject
+ niceMockForProtocol:@protocol(TouchToSearchPermissionsChangeAudience)];
+ [permissions setAudience:audience];
+ EXPECT_EQ(nil, [permissions audience]);
+}
+
+TEST_F(TouchToSearchPermissionsMediatorTest, AudienceRemovedNotifications) {
+ base::scoped_nsobject<id> audience(
+ [[TestTouchToSearchPermissionsAudience alloc] init]);
+ [tts_permissions_ setAudience:audience];
+ EXPECT_TRUE([tts_permissions_ observing]);
+ audience.reset();
+ // Permissions shouldn't be observing after notifying a nil audience.
+ [[NSNotificationCenter defaultCenter]
+ postNotificationName:UIAccessibilityVoiceOverStatusChanged
+ object:nil];
+ EXPECT_FALSE([tts_permissions_ observing]);
+
+ // Permissions shouldn't observe while still observing.
+ audience.reset([[TestTouchToSearchPermissionsAudience alloc] init]);
+ [tts_permissions_ setAudience:audience];
+ audience.reset();
+ audience.reset([[TestTouchToSearchPermissionsAudience alloc] init]);
+ [tts_permissions_ setAudience:audience];
+}
+
+#pragma mark - Unit tests for availability class method.
+
+TEST(TouchToSearchPermissionsAvailabilityTest, CommandLinePermissions) {
+ const struct {
+ bool set_disable;
+ bool set_enable;
+ bool expect_available;
+ } tests[] = {
+ {true, false, false},
+ {true, true, false},
+ {false, false, false},
+ {false, true, true},
+ };
+
+ for (const auto& test : tests) {
+ // Reset all flags.
+ base::CommandLine::ForCurrentProcess()->InitFromArgv(0, NULL);
+ if (test.set_disable) {
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kDisableContextualSearch);
+ }
+ if (test.set_enable) {
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableContextualSearch);
+ }
+ EXPECT_EQ(
+ [TouchToSearchPermissionsMediator isTouchToSearchAvailableOnDevice],
+ test.expect_available);
+ }
+}
+
+TEST(TouchToSearchPermissionsAvailabilityTest, FieldTrial) {
+ const struct {
+ const std::string trial_group_name;
+ bool expect_available;
+ } tests[] = {
+ {"Enabled", true},
+ {"Disabled", false},
+ {"Control", false},
+ {"Spadoinkle", false},
+ };
+
+ // Reset all flags.
+ base::CommandLine::ForCurrentProcess()->InitFromArgv(0, NULL);
+
+ for (const auto& test : tests) {
+ base::FieldTrialList field_trial_list(nullptr);
+ if (!test.trial_group_name.empty()) {
+ base::FieldTrialList::CreateFieldTrial("ContextualSearchIOS",
+ test.trial_group_name);
+ }
+ EXPECT_EQ(
+ [TouchToSearchPermissionsMediator isTouchToSearchAvailableOnDevice],
+ test.expect_available);
+ }
+}
+
+#pragma mark - Unit tests for mock class
+
+TEST(MockTouchToSearchPermissionsTest, Mocking) {
+ base::scoped_nsobject<MockTouchToSearchPermissionsMediator>
+ scoped_permissions([[MockTouchToSearchPermissionsMediator alloc]
+ initWithBrowserState:nullptr]);
+ MockTouchToSearchPermissionsMediator* permissions = scoped_permissions;
+
+ const GURL test_urls[] = {
+ GURL("https://www.some-website.com/"),
+ GURL("http://www.some-website.com/"), GURL(""),
+ };
+
+ // Default expectations from mocked methods.
+ EXPECT_TRUE([[permissions class] isTouchToSearchAvailableOnDevice]);
+ EXPECT_TRUE([permissions canSendPageURLs]);
+ EXPECT_TRUE([permissions canPreloadSearchResults]);
+ EXPECT_FALSE([permissions isVoiceOverEnabled]);
+ EXPECT_TRUE([permissions areContextualSearchQueriesSupported]);
+ for (const auto& url : test_urls)
+ EXPECT_TRUE([permissions canExtractTapContextForURL:url]);
+
+ // Set non-default values:
+ for (const BOOL value : {NO, YES, NO, YES}) {
+ [[permissions class] setIsTouchToSearchAvailableOnDevice:value];
+ EXPECT_EQ(value, [[permissions class] isTouchToSearchAvailableOnDevice]);
+ permissions.canSendPageURLs = value;
+ EXPECT_EQ(value, [permissions canSendPageURLs]);
+ permissions.canPreloadSearchResults = value;
+ EXPECT_EQ(value, [permissions canPreloadSearchResults]);
+ permissions.isVoiceOverEnabled = value;
+ EXPECT_EQ(value, [permissions isVoiceOverEnabled]);
+ permissions.areContextualSearchQueriesSupported = value;
+ EXPECT_EQ(value, [permissions areContextualSearchQueriesSupported]);
+ permissions.canExtractTapContextForAllURLs = value;
+ for (const auto& url : test_urls) {
+ EXPECT_EQ(value, [permissions canExtractTapContextForURL:url]);
+ }
+ }
+
+ const TouchToSearch::TouchToSearchPreferenceState states[] = {
+ TouchToSearch::DISABLED, TouchToSearch::UNDECIDED, TouchToSearch::ENABLED,
+ };
+
+ for (const auto& state : states) {
+ permissions.preferenceState = state;
+ EXPECT_EQ(state, permissions.preferenceState);
+ }
+}
+
+} // namespace

Powered by Google App Engine
This is Rietveld 408576698