Home | History | Annotate | Download | only in translate
      1 // Copyright 2013 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 #include "chrome/browser/ui/views/translate/translate_bubble_view.h"
      6 
      7 #include "base/memory/scoped_ptr.h"
      8 #include "chrome/browser/ui/translate/translate_bubble_model.h"
      9 #include "chrome/browser/ui/translate/translate_bubble_view_state_transition.h"
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 #include "ui/views/controls/button/checkbox.h"
     12 #include "ui/views/controls/combobox/combobox.h"
     13 #include "ui/views/test/views_test_base.h"
     14 #include "ui/views/widget/widget.h"
     15 
     16 namespace {
     17 
     18 class MockTranslateBubbleModel : public TranslateBubbleModel {
     19  public:
     20   explicit MockTranslateBubbleModel(TranslateBubbleModel::ViewState view_state)
     21       : view_state_transition_(view_state),
     22         error_type_(translate::TranslateErrors::NONE),
     23         original_language_index_(0),
     24         target_language_index_(1),
     25         never_translate_language_(false),
     26         never_translate_site_(false),
     27         should_always_translate_(false),
     28         set_always_translate_called_count_(0),
     29         translate_called_(false),
     30         revert_translation_called_(false),
     31         translation_declined_called_(false),
     32         original_language_index_on_translation_(-1),
     33         target_language_index_on_translation_(-1) {}
     34 
     35   virtual TranslateBubbleModel::ViewState GetViewState() const OVERRIDE {
     36     return view_state_transition_.view_state();
     37   }
     38 
     39   virtual void SetViewState(TranslateBubbleModel::ViewState view_state)
     40       OVERRIDE {
     41     view_state_transition_.SetViewState(view_state);
     42   }
     43 
     44   virtual void ShowError(translate::TranslateErrors::Type error_type) OVERRIDE {
     45     error_type_ = error_type;
     46   }
     47 
     48   virtual void GoBackFromAdvanced() OVERRIDE {
     49     view_state_transition_.GoBackFromAdvanced();
     50   }
     51 
     52   virtual int GetNumberOfLanguages() const OVERRIDE {
     53     return 1000;
     54   }
     55 
     56   virtual base::string16 GetLanguageNameAt(int index) const OVERRIDE {
     57     return base::string16();
     58   }
     59 
     60   virtual int GetOriginalLanguageIndex() const OVERRIDE {
     61     return original_language_index_;
     62   }
     63 
     64   virtual void UpdateOriginalLanguageIndex(int index) OVERRIDE {
     65     original_language_index_ = index;
     66   }
     67 
     68   virtual int GetTargetLanguageIndex() const OVERRIDE {
     69     return target_language_index_;
     70   }
     71 
     72   virtual void UpdateTargetLanguageIndex(int index) OVERRIDE {
     73     target_language_index_ = index;
     74   }
     75 
     76   virtual void SetNeverTranslateLanguage(bool value) OVERRIDE {
     77     never_translate_language_ = value;
     78   }
     79 
     80   virtual void SetNeverTranslateSite(bool value) OVERRIDE {
     81     never_translate_site_ = value;
     82   }
     83 
     84   virtual bool ShouldAlwaysTranslate() const OVERRIDE {
     85     return should_always_translate_;
     86   }
     87 
     88   virtual void SetAlwaysTranslate(bool value) OVERRIDE {
     89     should_always_translate_ = value;
     90     set_always_translate_called_count_++;
     91   }
     92 
     93   virtual void Translate() OVERRIDE {
     94     translate_called_ = true;
     95     original_language_index_on_translation_ = original_language_index_;
     96     target_language_index_on_translation_ = target_language_index_;
     97   }
     98 
     99   virtual void RevertTranslation() OVERRIDE {
    100     revert_translation_called_ = true;
    101   }
    102 
    103   virtual void TranslationDeclined(bool explicitly_closed) OVERRIDE {
    104     translation_declined_called_ = true;
    105   }
    106 
    107   virtual bool IsPageTranslatedInCurrentLanguages() const OVERRIDE {
    108     return original_language_index_on_translation_ ==
    109         original_language_index_ &&
    110         target_language_index_on_translation_ == target_language_index_;
    111   }
    112 
    113   TranslateBubbleViewStateTransition view_state_transition_;
    114   translate::TranslateErrors::Type error_type_;
    115   int original_language_index_;
    116   int target_language_index_;
    117   bool never_translate_language_;
    118   bool never_translate_site_;
    119   bool should_always_translate_;
    120   int set_always_translate_called_count_;
    121   bool translate_called_;
    122   bool revert_translation_called_;
    123   bool translation_declined_called_;
    124   int original_language_index_on_translation_;
    125   int target_language_index_on_translation_;
    126 };
    127 
    128 }  // namespace
    129 
    130 class TranslateBubbleViewTest : public views::ViewsTestBase {
    131  public:
    132   TranslateBubbleViewTest() {
    133   }
    134 
    135  protected:
    136   virtual void SetUp() OVERRIDE {
    137     views::ViewsTestBase::SetUp();
    138 
    139     // The bubble needs the parent as an anchor.
    140     views::Widget::InitParams params =
    141         CreateParams(views::Widget::InitParams::TYPE_WINDOW);
    142     params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    143 
    144     anchor_widget_.reset(new views::Widget());
    145     anchor_widget_->Init(params);
    146     anchor_widget_->Show();
    147 
    148     mock_model_ = new MockTranslateBubbleModel(
    149         TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE);
    150     scoped_ptr<TranslateBubbleModel> model(mock_model_);
    151     bubble_ = new TranslateBubbleView(anchor_widget_->GetContentsView(),
    152                                       model.Pass(),
    153                                       translate::TranslateErrors::NONE,
    154                                       NULL);
    155     views::BubbleDelegateView::CreateBubble(bubble_)->Show();
    156   }
    157 
    158   virtual void TearDown() OVERRIDE {
    159     bubble_->GetWidget()->CloseNow();
    160     anchor_widget_.reset();
    161 
    162     views::ViewsTestBase::TearDown();
    163   }
    164 
    165   scoped_ptr<views::Widget> anchor_widget_;
    166   MockTranslateBubbleModel* mock_model_;
    167   TranslateBubbleView* bubble_;
    168 };
    169 
    170 TEST_F(TranslateBubbleViewTest, TranslateButton) {
    171   EXPECT_FALSE(mock_model_->translate_called_);
    172 
    173   // Press the "Translate" button.
    174   bubble_->HandleButtonPressed(TranslateBubbleView::BUTTON_ID_TRANSLATE);
    175   EXPECT_TRUE(mock_model_->translate_called_);
    176 }
    177 
    178 TEST_F(TranslateBubbleViewTest, AdvancedLink) {
    179   EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE,
    180             bubble_->GetViewState());
    181 
    182   // Click the "Advanced" link.
    183   bubble_->HandleLinkClicked(TranslateBubbleView::LINK_ID_ADVANCED);
    184   EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_ADVANCED, bubble_->GetViewState());
    185 }
    186 
    187 TEST_F(TranslateBubbleViewTest, ShowOriginalButton) {
    188   bubble_->SwitchView(TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE);
    189 
    190   // Click the "Show original" button to revert translation.
    191   EXPECT_FALSE(mock_model_->revert_translation_called_);
    192   bubble_->HandleButtonPressed(TranslateBubbleView::BUTTON_ID_SHOW_ORIGINAL);
    193   EXPECT_TRUE(mock_model_->revert_translation_called_);
    194 }
    195 
    196 TEST_F(TranslateBubbleViewTest, TryAgainButton) {
    197   bubble_->SwitchToErrorView(translate::TranslateErrors::NETWORK);
    198 
    199   EXPECT_EQ(translate::TranslateErrors::NETWORK, mock_model_->error_type_);
    200 
    201   // Click the "Try again" button to translate.
    202   EXPECT_FALSE(mock_model_->translate_called_);
    203   bubble_->HandleButtonPressed(TranslateBubbleView::BUTTON_ID_TRY_AGAIN);
    204   EXPECT_TRUE(mock_model_->translate_called_);
    205 }
    206 
    207 TEST_F(TranslateBubbleViewTest, AlwaysTranslateCheckboxAndCancelButton) {
    208   bubble_->SwitchView(TranslateBubbleModel::VIEW_STATE_ADVANCED);
    209 
    210   // Click the "Always Translate" checkbox. Changing the state of this checkbox
    211   // should NOT affect the model after pressing the cancel button.
    212 
    213   // Check the initial state.
    214   EXPECT_FALSE(mock_model_->should_always_translate_);
    215   EXPECT_EQ(0, mock_model_->set_always_translate_called_count_);
    216   EXPECT_FALSE(bubble_->always_translate_checkbox_->checked());
    217 
    218   // Click the checkbox. The state is not saved yet.
    219   bubble_->always_translate_checkbox_->SetChecked(true);
    220   bubble_->HandleButtonPressed(TranslateBubbleView::BUTTON_ID_ALWAYS_TRANSLATE);
    221   EXPECT_FALSE(mock_model_->should_always_translate_);
    222   EXPECT_EQ(0, mock_model_->set_always_translate_called_count_);
    223 
    224   // Click the cancel button. The state is not saved.
    225   bubble_->HandleButtonPressed(TranslateBubbleView::BUTTON_ID_CANCEL);
    226   EXPECT_FALSE(mock_model_->should_always_translate_);
    227   EXPECT_EQ(0, mock_model_->set_always_translate_called_count_);
    228 }
    229 
    230 TEST_F(TranslateBubbleViewTest, AlwaysTranslateCheckboxAndDoneButton) {
    231   bubble_->SwitchView(TranslateBubbleModel::VIEW_STATE_ADVANCED);
    232 
    233   // Click the "Always Translate" checkbox. Changing the state of this checkbox
    234   // should affect the model after pressing the done button.
    235 
    236   // Check the initial state.
    237   EXPECT_FALSE(mock_model_->should_always_translate_);
    238   EXPECT_EQ(0, mock_model_->set_always_translate_called_count_);
    239   EXPECT_FALSE(bubble_->always_translate_checkbox_->checked());
    240 
    241   // Click the checkbox. The state is not saved yet.
    242   bubble_->always_translate_checkbox_->SetChecked(true);
    243   bubble_->HandleButtonPressed(TranslateBubbleView::BUTTON_ID_ALWAYS_TRANSLATE);
    244   EXPECT_FALSE(mock_model_->should_always_translate_);
    245   EXPECT_EQ(0, mock_model_->set_always_translate_called_count_);
    246 
    247   // Click the done button. The state is saved.
    248   bubble_->HandleButtonPressed(TranslateBubbleView::BUTTON_ID_DONE);
    249   EXPECT_TRUE(mock_model_->should_always_translate_);
    250   EXPECT_EQ(1, mock_model_->set_always_translate_called_count_);
    251 }
    252 
    253 TEST_F(TranslateBubbleViewTest, DoneButton) {
    254   bubble_->SwitchView(TranslateBubbleModel::VIEW_STATE_ADVANCED);
    255 
    256   // Click the "Done" button to translate. The selected languages by the user
    257   // are applied.
    258   EXPECT_FALSE(mock_model_->translate_called_);
    259   bubble_->source_language_combobox_->SetSelectedIndex(10);
    260   bubble_->HandleComboboxPerformAction(
    261       TranslateBubbleView::COMBOBOX_ID_SOURCE_LANGUAGE);
    262   bubble_->target_language_combobox_->SetSelectedIndex(20);
    263   bubble_->HandleComboboxPerformAction(
    264       TranslateBubbleView::COMBOBOX_ID_TARGET_LANGUAGE);
    265   bubble_->HandleButtonPressed(TranslateBubbleView::BUTTON_ID_DONE);
    266   EXPECT_TRUE(mock_model_->translate_called_);
    267   EXPECT_EQ(10, mock_model_->original_language_index_);
    268   EXPECT_EQ(20, mock_model_->target_language_index_);
    269 }
    270 
    271 TEST_F(TranslateBubbleViewTest, DoneButtonWithoutTranslating) {
    272   EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE,
    273             bubble_->GetViewState());
    274 
    275   // Translate the page once.
    276   mock_model_->Translate();
    277   EXPECT_TRUE(mock_model_->translate_called_);
    278 
    279   // Go back to the initial view.
    280   EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE,
    281             bubble_->GetViewState());
    282   mock_model_->translate_called_ = false;
    283 
    284   EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE,
    285             bubble_->GetViewState());
    286   bubble_->SwitchView(TranslateBubbleModel::VIEW_STATE_ADVANCED);
    287 
    288   // Click the "Done" button with the current language pair. This time,
    289   // translation is not performed and the view state will be back to the
    290   // previous view.
    291   bubble_->HandleButtonPressed(TranslateBubbleView::BUTTON_ID_DONE);
    292   EXPECT_FALSE(mock_model_->translate_called_);
    293 
    294   EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE,
    295             bubble_->GetViewState());
    296 }
    297 
    298 TEST_F(TranslateBubbleViewTest, CancelButtonReturningBeforeTranslate) {
    299   bubble_->SwitchView(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE);
    300   bubble_->SwitchView(TranslateBubbleModel::VIEW_STATE_ADVANCED);
    301 
    302   // Click the "Cancel" button to go back.
    303   EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_ADVANCED, bubble_->GetViewState());
    304   bubble_->HandleButtonPressed(TranslateBubbleView::BUTTON_ID_CANCEL);
    305   EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE,
    306             bubble_->GetViewState());
    307 }
    308 
    309 TEST_F(TranslateBubbleViewTest, CancelButtonReturningAfterTranslate) {
    310   bubble_->SwitchView(TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE);
    311   bubble_->SwitchView(TranslateBubbleModel::VIEW_STATE_ADVANCED);
    312 
    313   // Click the "Cancel" button to go back.
    314   EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_ADVANCED, bubble_->GetViewState());
    315   bubble_->HandleButtonPressed(TranslateBubbleView::BUTTON_ID_CANCEL);
    316   EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE,
    317             bubble_->GetViewState());
    318 }
    319 
    320 TEST_F(TranslateBubbleViewTest, CancelButtonReturningError) {
    321   bubble_->SwitchView(TranslateBubbleModel::VIEW_STATE_ERROR);
    322   bubble_->SwitchView(TranslateBubbleModel::VIEW_STATE_ADVANCED);
    323 
    324   // Click the "Cancel" button to go back.
    325   EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_ADVANCED, bubble_->GetViewState());
    326   bubble_->HandleButtonPressed(TranslateBubbleView::BUTTON_ID_CANCEL);
    327   EXPECT_EQ(TranslateBubbleModel::VIEW_STATE_ERROR, bubble_->GetViewState());
    328 }
    329