Home | History | Annotate | Download | only in translate
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #import <Cocoa/Cocoa.h>
      6 
      7 #import "base/memory/scoped_nsobject.h"
      8 #import "base/string_util.h"
      9 #include "base/utf_string_conversions.h"
     10 #import "chrome/app/chrome_command_ids.h"  // For translate menu command ids.
     11 #import "chrome/browser/translate/translate_infobar_delegate.h"
     12 #import "chrome/browser/ui/cocoa/browser_test_helper.h"
     13 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
     14 #import "chrome/browser/ui/cocoa/infobars/infobar.h"
     15 #import "chrome/browser/ui/cocoa/translate/translate_infobar_base.h"
     16 #import "chrome/browser/ui/cocoa/translate/before_translate_infobar_controller.h"
     17 #import "content/browser/site_instance.h"
     18 #import "content/browser/tab_contents/tab_contents.h"
     19 #import "testing/gmock/include/gmock/gmock.h"
     20 #import "testing/gtest/include/gtest/gtest.h"
     21 #import "testing/platform_test.h"
     22 
     23 namespace {
     24 
     25 // All states the translate toolbar can assume.
     26 TranslateInfoBarDelegate::Type kTranslateToolbarStates[] = {
     27   TranslateInfoBarDelegate::BEFORE_TRANSLATE,
     28   TranslateInfoBarDelegate::AFTER_TRANSLATE,
     29   TranslateInfoBarDelegate::TRANSLATING,
     30   TranslateInfoBarDelegate::TRANSLATION_ERROR
     31 };
     32 
     33 class MockTranslateInfoBarDelegate : public TranslateInfoBarDelegate {
     34  public:
     35   MockTranslateInfoBarDelegate(TranslateInfoBarDelegate::Type type,
     36                                TranslateErrors::Type error,
     37                                TabContents* contents)
     38       : TranslateInfoBarDelegate(type, error, contents, "en", "es"){
     39     // Start out in the "Before Translate" state.
     40     type_ = type;
     41 
     42   }
     43 
     44   virtual string16 GetDisplayNameForLocale(const std::string& language_code) {
     45     return ASCIIToUTF16("Foo");
     46   }
     47 
     48   virtual bool IsLanguageBlacklisted() {
     49     return false;
     50   }
     51 
     52   virtual bool IsSiteBlacklisted() {
     53     return false;
     54   }
     55 
     56   virtual bool ShouldAlwaysTranslate() {
     57     return false;
     58   }
     59 
     60   MOCK_METHOD0(Translate, void());
     61   MOCK_METHOD0(RevertTranslation, void());
     62   MOCK_METHOD0(TranslationDeclined, void());
     63   MOCK_METHOD0(ToggleLanguageBlacklist, void());
     64   MOCK_METHOD0(ToggleSiteBlacklist, void());
     65   MOCK_METHOD0(ToggleAlwaysTranslate, void());
     66 };
     67 
     68 class TranslationInfoBarTest : public CocoaTest {
     69  public:
     70   BrowserTestHelper browser_helper_;
     71   scoped_ptr<TabContents> tab_contents;
     72   scoped_ptr<MockTranslateInfoBarDelegate> infobar_delegate;
     73   scoped_nsobject<TranslateInfoBarControllerBase> infobar_controller;
     74 
     75  public:
     76   // Each test gets a single Mock translate delegate for the lifetime of
     77   // the test.
     78   virtual void SetUp() {
     79     CocoaTest::SetUp();
     80    tab_contents.reset(
     81         new TabContents(browser_helper_.profile(),
     82                         NULL,
     83                         MSG_ROUTING_NONE,
     84                         NULL,
     85                         NULL));
     86     CreateInfoBar();
     87   }
     88 
     89   void CreateInfoBar() {
     90     CreateInfoBar(TranslateInfoBarDelegate::BEFORE_TRANSLATE);
     91   }
     92 
     93   void CreateInfoBar(TranslateInfoBarDelegate::Type type) {
     94     TranslateErrors::Type error = TranslateErrors::NONE;
     95     if (type == TranslateInfoBarDelegate::TRANSLATION_ERROR)
     96       error = TranslateErrors::NETWORK;
     97     infobar_delegate.reset(
     98         new MockTranslateInfoBarDelegate(type, error, tab_contents.get()));
     99     [[infobar_controller view] removeFromSuperview];
    100     scoped_ptr<InfoBar> infobar(
    101         static_cast<InfoBarDelegate*>(infobar_delegate.get())->CreateInfoBar());
    102     infobar_controller.reset(
    103         reinterpret_cast<TranslateInfoBarControllerBase*>(
    104             infobar->controller()));
    105     // We need to set the window to be wide so that the options button
    106     // doesn't overlap the other buttons.
    107     [test_window() setContentSize:NSMakeSize(2000, 500)];
    108     [[infobar_controller view] setFrame:NSMakeRect(0, 0, 2000, 500)];
    109     [[test_window() contentView] addSubview:[infobar_controller view]];
    110   }
    111 };
    112 
    113 // Check that we can instantiate a Translate Infobar correctly.
    114 TEST_F(TranslationInfoBarTest, Instantiate) {
    115   CreateInfoBar();
    116   ASSERT_TRUE(infobar_controller.get());
    117 }
    118 
    119 // Check that clicking the Translate button calls Translate().
    120 TEST_F(TranslationInfoBarTest, TranslateCalledOnButtonPress) {
    121   CreateInfoBar();
    122 
    123   EXPECT_CALL(*infobar_delegate, Translate()).Times(1);
    124   [infobar_controller ok:nil];
    125 }
    126 
    127 // Check that clicking the "Retry" button calls Translate() when we're
    128 // in the error mode - http://crbug.com/41315 .
    129 TEST_F(TranslationInfoBarTest, TranslateCalledInErrorMode) {
    130   CreateInfoBar(TranslateInfoBarDelegate::TRANSLATION_ERROR);
    131 
    132   EXPECT_CALL(*infobar_delegate, Translate()).Times(1);
    133 
    134   [infobar_controller ok:nil];
    135 }
    136 
    137 // Check that clicking the "Show Original button calls RevertTranslation().
    138 TEST_F(TranslationInfoBarTest, RevertCalledOnButtonPress) {
    139   CreateInfoBar();
    140 
    141   EXPECT_CALL(*infobar_delegate, RevertTranslation()).Times(1);
    142   [infobar_controller showOriginal:nil];
    143 }
    144 
    145 // Check that items in the options menu are hooked up correctly.
    146 TEST_F(TranslationInfoBarTest, OptionsMenuItemsHookedUp) {
    147   EXPECT_CALL(*infobar_delegate, Translate())
    148     .Times(0);
    149 
    150   [infobar_controller rebuildOptionsMenu:NO];
    151   NSMenu* optionsMenu = [infobar_controller optionsMenu];
    152   NSArray* optionsMenuItems = [optionsMenu itemArray];
    153 
    154   EXPECT_EQ(7U, [optionsMenuItems count]);
    155 
    156   // First item is the options menu button's title, so there's no need to test
    157   // that the target on that is setup correctly.
    158   for (NSUInteger i = 1; i < [optionsMenuItems count]; ++i) {
    159     NSMenuItem* item = [optionsMenuItems objectAtIndex:i];
    160     if (![item isSeparatorItem])
    161       EXPECT_EQ([item target], infobar_controller.get());
    162   }
    163   NSMenuItem* alwaysTranslateLanguateItem = [optionsMenuItems objectAtIndex:1];
    164   NSMenuItem* neverTranslateLanguateItem = [optionsMenuItems objectAtIndex:2];
    165   NSMenuItem* neverTranslateSiteItem = [optionsMenuItems objectAtIndex:3];
    166   // Separator at 4.
    167   NSMenuItem* reportBadLanguageItem = [optionsMenuItems objectAtIndex:5];
    168   NSMenuItem* aboutTranslateItem = [optionsMenuItems objectAtIndex:6];
    169 
    170   {
    171     EXPECT_CALL(*infobar_delegate, ToggleAlwaysTranslate())
    172     .Times(1);
    173     [infobar_controller optionsMenuChanged:alwaysTranslateLanguateItem];
    174   }
    175 
    176   {
    177     EXPECT_CALL(*infobar_delegate, ToggleLanguageBlacklist())
    178     .Times(1);
    179     [infobar_controller optionsMenuChanged:neverTranslateLanguateItem];
    180   }
    181 
    182   {
    183     EXPECT_CALL(*infobar_delegate, ToggleSiteBlacklist())
    184     .Times(1);
    185     [infobar_controller optionsMenuChanged:neverTranslateSiteItem];
    186   }
    187 
    188   {
    189     // Can't mock these effectively, so just check that the tag is set
    190     // correctly.
    191     EXPECT_EQ(IDC_TRANSLATE_REPORT_BAD_LANGUAGE_DETECTION,
    192               [reportBadLanguageItem tag]);
    193     EXPECT_EQ(IDC_TRANSLATE_OPTIONS_ABOUT, [aboutTranslateItem tag]);
    194   }
    195 }
    196 
    197 // Check that selecting a new item from the "Source Language" popup in "before
    198 // translate" mode doesn't trigger a translation or change state.
    199 // http://crbug.com/36666
    200 TEST_F(TranslationInfoBarTest, Bug36666) {
    201   EXPECT_CALL(*infobar_delegate, Translate())
    202     .Times(0);
    203 
    204   CreateInfoBar();
    205   int arbitrary_index = 2;
    206   [infobar_controller sourceLanguageModified:arbitrary_index];
    207   EXPECT_CALL(*infobar_delegate, Translate())
    208     .Times(0);
    209 }
    210 
    211 // Check that the infobar lays itself out correctly when instantiated in
    212 // each of the states.
    213 // http://crbug.com/36895
    214 TEST_F(TranslationInfoBarTest, Bug36895) {
    215   EXPECT_CALL(*infobar_delegate, Translate())
    216     .Times(0);
    217 
    218   for (size_t i = 0; i < arraysize(kTranslateToolbarStates); ++i) {
    219     CreateInfoBar(kTranslateToolbarStates[i]);
    220     EXPECT_TRUE(
    221         [infobar_controller verifyLayout]) << "Layout wrong, for state #" << i;
    222   }
    223 }
    224 
    225 // Verify that the infobar shows the "Always translate this language" button
    226 // after doing 3 translations.
    227 TEST_F(TranslationInfoBarTest, TriggerShowAlwaysTranslateButton) {
    228   TranslatePrefs translate_prefs(browser_helper_.profile()->GetPrefs());
    229   translate_prefs.ResetTranslationAcceptedCount("en");
    230   for (int i = 0; i < 4; ++i) {
    231     translate_prefs.IncrementTranslationAcceptedCount("en");
    232   }
    233   CreateInfoBar(TranslateInfoBarDelegate::BEFORE_TRANSLATE);
    234   BeforeTranslateInfobarController* controller =
    235       (BeforeTranslateInfobarController*)infobar_controller.get();
    236   EXPECT_TRUE([[controller alwaysTranslateButton] superview] !=  nil);
    237   EXPECT_TRUE([[controller neverTranslateButton] superview] == nil);
    238 }
    239 
    240 // Verify that the infobar shows the "Never translate this language" button
    241 // after denying 3 translations.
    242 TEST_F(TranslationInfoBarTest, TriggerShowNeverTranslateButton) {
    243   TranslatePrefs translate_prefs(browser_helper_.profile()->GetPrefs());
    244   translate_prefs.ResetTranslationDeniedCount("en");
    245   for (int i = 0; i < 4; ++i) {
    246     translate_prefs.IncrementTranslationDeniedCount("en");
    247   }
    248   CreateInfoBar(TranslateInfoBarDelegate::BEFORE_TRANSLATE);
    249   BeforeTranslateInfobarController* controller =
    250       (BeforeTranslateInfobarController*)infobar_controller.get();
    251   EXPECT_TRUE([[controller alwaysTranslateButton] superview] == nil);
    252   EXPECT_TRUE([[controller neverTranslateButton] superview] != nil);
    253 }
    254 
    255 } // namespace
    256