chromium/chrome/browser/renderer_context_menu/spelling_menu_observer_browsertest.cc

// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/renderer_context_menu/spelling_menu_observer.h"

#include <memory>

#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/renderer_context_menu/mock_render_view_context_menu.h"
#include "chrome/browser/spellchecker/spellcheck_factory.h"
#include "chrome/browser/spellchecker/spellcheck_service.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "components/prefs/pref_service.h"
#include "components/spellcheck/browser/pref_names.h"
#include "components/spellcheck/browser/spelling_service_client.h"
#include "components/spellcheck/common/spellcheck_features.h"
#include "components/spellcheck/spellcheck_buildflags.h"
#include "content/public/browser/context_menu_params.h"
#include "content/public/test/browser_test.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

// A test class used in this file. This test should be a browser test because it
// accesses resources.
class SpellingMenuObserverTest : public InProcessBrowserTest {};

#if BUILDFLAG(IS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER)
SpellingMenuObserverTest::SpellingMenuObserverTest() {
  feature_list_.InitWithFeatures(
      /*enabled_features=*/{spellcheck::kWinRetrieveSuggestionsOnlyOnDemand},
      /*disabled_features=*/{spellcheck::kWinDelaySpellcheckServiceInit});
}
#else
SpellingMenuObserverTest::SpellingMenuObserverTest() = default;
#endif  // BUILDFLAG(IS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER)

SpellingMenuObserverTest::~SpellingMenuObserverTest() = default;

}  // namespace

// Tests that right-clicking a correct word does not add any items.
IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest, InitMenuWithCorrectWord) {}

// Tests that right-clicking a misspelled word adds two items:
// "Add to dictionary", "Use enhanced spell check".
IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest, InitMenuWithMisspelledWord) {}

#if BUILDFLAG(IS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER)
// Tests that right-clicking a misspelled word that is identified as misspelled
// by both Hunspell and Windows platform combines their suggestions.
IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest,
                       WinInitMenuWithMisspelledWordCombined) {
  InitMenu("mispelled", "misspelling");
  EXPECT_EQ(6U, menu()->GetMenuSize());

  // Read all the context-menu items added by this test and verify they are
  // expected ones.
  MockRenderViewContextMenu::MockMenuItem item;
  // First separator.
  menu()->GetMenuItem(0, &item);
  EXPECT_EQ(-1, item.command_id);
  EXPECT_FALSE(item.enabled);
  EXPECT_FALSE(item.hidden);
  // First suggestion.
  menu()->GetMenuItem(1, &item);
  EXPECT_EQ(IDC_SPELLCHECK_SUGGESTION_0, item.command_id);
  EXPECT_TRUE(item.enabled);
  EXPECT_FALSE(item.hidden);
  EXPECT_EQ(u"misspelled", item.title);
  // Second suggestion.
  menu()->GetMenuItem(2, &item);
  EXPECT_EQ(IDC_SPELLCHECK_SUGGESTION_0 + 1, item.command_id);
  EXPECT_TRUE(item.enabled);
  EXPECT_FALSE(item.hidden);
  EXPECT_EQ(u"misspelling", item.title);
  // Second separator.
  menu()->GetMenuItem(3, &item);
  EXPECT_EQ(-1, item.command_id);
  EXPECT_FALSE(item.enabled);
  EXPECT_FALSE(item.hidden);
  // Add to dictionary.
  menu()->GetMenuItem(4, &item);
  EXPECT_EQ(IDC_SPELLCHECK_ADD_TO_DICTIONARY, item.command_id);
  EXPECT_TRUE(item.enabled);
  EXPECT_FALSE(item.hidden);
  // Enhanced spellcheck toggle.
  menu()->GetMenuItem(5, &item);
  EXPECT_EQ(IDC_CONTENT_CONTEXT_SPELLING_TOGGLE, item.command_id);
  EXPECT_TRUE(item.enabled);
  EXPECT_FALSE(item.checked);
  EXPECT_FALSE(item.hidden);
}

// Tests that right-clicking a misspelled word that is identified as misspelled
// by both Hunspell and Windows platform with the same suggestion leads to a
// single suggestion.
IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest,
                       WinInitMenuWithMisspelledWordNoDuplicateSuggestions) {
  InitMenu("mispelled", "misspelled");
  EXPECT_EQ(5U, menu()->GetMenuSize());

  // Read all the context-menu items added by this test and verify they are
  // expected ones.
  MockRenderViewContextMenu::MockMenuItem item;
  // First separator.
  menu()->GetMenuItem(0, &item);
  EXPECT_EQ(-1, item.command_id);
  EXPECT_FALSE(item.enabled);
  EXPECT_FALSE(item.hidden);
  // First and only suggestion.
  menu()->GetMenuItem(1, &item);
  EXPECT_EQ(IDC_SPELLCHECK_SUGGESTION_0, item.command_id);
  EXPECT_TRUE(item.enabled);
  EXPECT_FALSE(item.hidden);
  EXPECT_EQ(u"misspelled", item.title);
  // Second separator.
  menu()->GetMenuItem(2, &item);
  EXPECT_EQ(-1, item.command_id);
  EXPECT_FALSE(item.enabled);
  EXPECT_FALSE(item.hidden);
  // Add to dictionary.
  menu()->GetMenuItem(3, &item);
  EXPECT_EQ(IDC_SPELLCHECK_ADD_TO_DICTIONARY, item.command_id);
  EXPECT_TRUE(item.enabled);
  EXPECT_FALSE(item.hidden);
  // Enhanced spellcheck toggle.
  menu()->GetMenuItem(4, &item);
  EXPECT_EQ(IDC_CONTENT_CONTEXT_SPELLING_TOGGLE, item.command_id);
  EXPECT_TRUE(item.enabled);
  EXPECT_FALSE(item.checked);
  EXPECT_FALSE(item.hidden);
}

// Tests that right-clicking a misspelled word that is identified as misspelled
// by both Hunspell and Windows platform that has > 3 suggestions only displays
// 3 suggestions.
IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest,
                       WinInitMenuWithMisspelledWordMaxSuggestions) {
  InitMenu("wtree", "wee");
  EXPECT_EQ(7U, menu()->GetMenuSize());

  std::set<std::u16string> suggestions(
      {u"tree", u"twee", u"wee", u"ware", u"were"});
  bool wee_suggested = false;
  for (unsigned int i = 1; i < menu()->GetMenuSize(); i++) {
    MockRenderViewContextMenu::MockMenuItem item;
    menu()->GetMenuItem(i, &item);
    if (!item.title.compare(u"wee")) {
      wee_suggested = true;
      break;
    }
  }
  EXPECT_TRUE(wee_suggested);
  // Read all the context-menu items added by this test and verify they are
  // among the expected possibilities.
  MockRenderViewContextMenu::MockMenuItem item;
  // First separator.
  menu()->GetMenuItem(0, &item);
  EXPECT_EQ(-1, item.command_id);
  EXPECT_FALSE(item.enabled);
  EXPECT_FALSE(item.hidden);
  // First suggestion.
  menu()->GetMenuItem(1, &item);
  EXPECT_EQ(IDC_SPELLCHECK_SUGGESTION_0, item.command_id);
  EXPECT_TRUE(item.enabled);
  EXPECT_FALSE(item.hidden);
  EXPECT_TRUE(suggestions.contains(item.title));
  // Second suggestion.
  menu()->GetMenuItem(2, &item);
  EXPECT_EQ(IDC_SPELLCHECK_SUGGESTION_0 + 1, item.command_id);
  EXPECT_TRUE(item.enabled);
  EXPECT_FALSE(item.hidden);
  EXPECT_TRUE(suggestions.contains(item.title));
  // Third suggestion.
  menu()->GetMenuItem(3, &item);
  EXPECT_EQ(IDC_SPELLCHECK_SUGGESTION_0 + 2, item.command_id);
  EXPECT_TRUE(item.enabled);
  EXPECT_FALSE(item.hidden);
  EXPECT_TRUE(suggestions.contains(item.title));
  // Second separator.
  menu()->GetMenuItem(4, &item);
  EXPECT_EQ(-1, item.command_id);
  EXPECT_FALSE(item.enabled);
  EXPECT_FALSE(item.hidden);
  // Add to dictionary.
  menu()->GetMenuItem(5, &item);
  EXPECT_EQ(IDC_SPELLCHECK_ADD_TO_DICTIONARY, item.command_id);
  EXPECT_TRUE(item.enabled);
  EXPECT_FALSE(item.hidden);
  // Enhanced spellcheck toggle.
  menu()->GetMenuItem(6, &item);
  EXPECT_EQ(IDC_CONTENT_CONTEXT_SPELLING_TOGGLE, item.command_id);
  EXPECT_TRUE(item.enabled);
  EXPECT_FALSE(item.checked);
  EXPECT_FALSE(item.hidden);
}
#endif  // BUILDFLAG(IS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER)

// Tests that right-clicking a correct word when we enable spelling-service
// integration to verify an item "Use enhanced spell check" is checked. Even
// though this menu itself does not add this item, its sub-menu adds the item
// and calls SpellingMenuObserver::IsChecked() to check it.
IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest,
                       EnableSpellingServiceWithCorrectWord) {}

// Tests that right-clicking a misspelled word when we enable spelling-service
// integration to verify an item "Use enhanced spell check" is checked. (This
// test does not actually send JSON-RPC requests to the service because it makes
// this test flaky.)
IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest, EnableSpellingService) {}

// Tests that right-clicking a misspelled word when spelling-service
// integration is enabled but the browser's spell check preference is disabled
// shows the "Use enhanced spell check" as unchecked. Clicking on this item
// enables spell check on the browser.
IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest,
                       EnableSpellingServiceWhenSpellcheckDisabled) {}

// Test that we don't show "No more suggestions from Google" if the spelling
// service is enabled and that there is only one suggestion.
IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest,
                       NoMoreSuggestionsNotDisplayed) {}

// crbug.com/899935
#if BUILDFLAG(IS_WIN)
#define MAYBE_NoSpellingServiceWhenOffTheRecord
#else
#define MAYBE_NoSpellingServiceWhenOffTheRecord
#endif

// Test that "Use enhanced spell check" is grayed out when using an
// off the record profile.
// TODO(rlp): Include graying out of autocorrect in this test when autocorrect
// is functional.
IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest,
                       MAYBE_NoSpellingServiceWhenOffTheRecord) {}

// crbug.com/899935
#if BUILDFLAG(IS_WIN)
#define MAYBE_SuggestionsForceTopSeparator
#else
#define MAYBE_SuggestionsForceTopSeparator
#endif

// Test that the menu is preceeded by a separator if there are any suggestions,
// or if the SpellingServiceClient is available
IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest,
                       MAYBE_SuggestionsForceTopSeparator) {}