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 "base/strings/stringprintf.h"
      6 #include "base/strings/utf_string_conversions.h"
      7 #include "chrome/test/base/chrome_render_view_test.h"
      8 #include "components/translate/core/common/translate_errors.h"
      9 #include "grit/component_resources.h"
     10 #include "third_party/WebKit/public/web/WebLocalFrame.h"
     11 #include "third_party/WebKit/public/web/WebScriptSource.h"
     12 #include "ui/base/resource/resource_bundle.h"
     13 #include "v8/include/v8.h"
     14 
     15 using blink::WebScriptSource;
     16 
     17 namespace {
     18 
     19 // JavaScript code to set runtime test flags.
     20 const char kThrowInitializationError[] = "throwInitializationError = true";
     21 const char kThrowUnexpectedScriptError[] = "throwUnexpectedScriptError = true";
     22 const char kCallbackReturnBooleanError[] = "callbackReturnBooleanError = true";
     23 const char kCallbackReturnNumberError[] = "callbackReturnNumberError = true";
     24 const char kSetCallbackErrorCode[] = "callbackErrorCode = ";
     25 
     26 // JavaScript code to check if any error happens.
     27 const char kError[] = "cr.googleTranslate.error";
     28 
     29 // JavaScript code to get error code.
     30 const char kErrorCode[] = "cr.googleTranslate.errorCode";
     31 
     32 // JavaScript code to check if the library is ready.
     33 const char kLibReady[] = "cr.googleTranslate.libReady";
     34 
     35 // JavaScript code to perform translation.
     36 const char kTranslate[] = "cr.googleTranslate.translate('auto', 'en')";
     37 
     38 // JavaScript code to mimic element.js provided by a translate server.
     39 const char kElementJs[] =
     40     "translateApiKey = '';"
     41     "google = {};"
     42     "google.translate = {};"
     43     "google.translate.TranslateService = function() {"
     44     "  if (window['throwInitializationError']) {"
     45     "    throw 'API initialization error';"
     46     "  }"
     47     "  return {"
     48     "    isAvailable: function() { return true; },"
     49     "    restore: function() {},"
     50     "    translatePage: function(originalLang, targetLang, cb) {"
     51     "      if (window['throwUnexpectedScriptError']) {"
     52     "        throw 'all your base are belong to us';"
     53     "      }"
     54     "      if (window['callbackReturnBooleanError']) {"
     55     "        cb(0, false, true);"
     56     "      }"
     57     "      if (window['callbackReturnNumberError']) {"
     58     "        cb(0, false, callbackErrorCode);"
     59     "      }"
     60     "    }"
     61     "  };"
     62     "};"
     63     "cr.googleTranslate.onTranslateElementLoad();";
     64 
     65 std::string GenerateSetCallbackErrorCodeScript(int code) {
     66   return base::StringPrintf("%s%d", kSetCallbackErrorCode, code);
     67 }
     68 
     69 };  // namespace
     70 
     71 // This class is for testing resource/translate.js works and reports errors
     72 // correctly.
     73 class TranslateScriptBrowserTest : public ChromeRenderViewTest {
     74  public:
     75   TranslateScriptBrowserTest() {}
     76 
     77  protected:
     78   void InjectElementLibrary() {
     79     std::string script;
     80     base::StringPiece translate_js = ResourceBundle::GetSharedInstance().
     81         GetRawDataResource(IDR_TRANSLATE_JS);
     82     translate_js.CopyToString(&script);
     83     script += kElementJs;
     84     ExecuteScript(script);
     85   }
     86 
     87   void ExecuteScript(const std::string& script) {
     88     WebScriptSource source = WebScriptSource(base::ASCIIToUTF16(script));
     89     GetMainFrame()->executeScript(source);
     90   }
     91 
     92   bool GetError() {
     93     return ExecuteScriptAndGetBoolResult(kError);
     94   }
     95 
     96   double GetErrorCode() {
     97     return ExecuteScriptAndGetNumberResult(kErrorCode);
     98   }
     99 
    100   bool IsLibReady() {
    101     return ExecuteScriptAndGetBoolResult(kLibReady);
    102   }
    103 
    104  private:
    105   virtual void SetUp() OVERRIDE {
    106     ChromeRenderViewTest::SetUp();
    107   }
    108 
    109   virtual void TearDown() OVERRIDE {
    110     ChromeRenderViewTest::TearDown();
    111   }
    112 
    113   double ExecuteScriptAndGetNumberResult(const std::string& script) {
    114     WebScriptSource source = WebScriptSource(base::ASCIIToUTF16(script));
    115     v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
    116     v8::Handle<v8::Value> result =
    117         GetMainFrame()->executeScriptAndReturnValue(source);
    118     if (result.IsEmpty() || !result->IsNumber()) {
    119       NOTREACHED();
    120       // TODO(toyoshim): Return NaN here and the real implementation in
    121       // TranslateHelper::ExecuteScriptAndGetDoubleResult().
    122       return 0.0;
    123     }
    124     return result->NumberValue();
    125   }
    126 
    127   bool ExecuteScriptAndGetBoolResult(const std::string& script) {
    128     WebScriptSource source = WebScriptSource(base::ASCIIToUTF16(script));
    129     v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
    130     v8::Handle<v8::Value> result =
    131         GetMainFrame()->executeScriptAndReturnValue(source);
    132     if (result.IsEmpty() || !result->IsBoolean()) {
    133       NOTREACHED();
    134       return false;
    135     }
    136     return result->BooleanValue();
    137   }
    138 
    139   DISALLOW_COPY_AND_ASSIGN(TranslateScriptBrowserTest);
    140 };
    141 
    142 // Test if onTranslateElementLoad() succeeds to initialize the element library.
    143 TEST_F(TranslateScriptBrowserTest, ElementLoadSuccess) {
    144   InjectElementLibrary();
    145   EXPECT_TRUE(IsLibReady());
    146   EXPECT_FALSE(GetError());
    147   EXPECT_EQ(TranslateErrors::NONE, GetErrorCode());
    148 }
    149 
    150 // Test if onTranslateElementLoad() fails to initialize the element library and
    151 // report the right error code.
    152 TEST_F(TranslateScriptBrowserTest, ElementLoadFailure) {
    153   ExecuteScript(kThrowInitializationError);
    154 
    155   InjectElementLibrary();
    156   EXPECT_FALSE(IsLibReady());
    157   EXPECT_TRUE(GetError());
    158   EXPECT_EQ(TranslateErrors::INITIALIZATION_ERROR, GetErrorCode());
    159 }
    160 
    161 // Test if cr.googleTranslate.translate() works.
    162 TEST_F(TranslateScriptBrowserTest, TranslateSuccess) {
    163   InjectElementLibrary();
    164   EXPECT_TRUE(IsLibReady());
    165   EXPECT_FALSE(GetError());
    166   EXPECT_EQ(TranslateErrors::NONE, GetErrorCode());
    167 
    168   ExecuteScript(kTranslate);
    169 
    170   EXPECT_FALSE(GetError());
    171   EXPECT_EQ(TranslateErrors::NONE, GetErrorCode());
    172 }
    173 
    174 // Test if cr.googleTranslate.translate() handles library exception correctly.
    175 TEST_F(TranslateScriptBrowserTest, TranslateFail) {
    176   ExecuteScript(kThrowUnexpectedScriptError);
    177 
    178   InjectElementLibrary();
    179   EXPECT_TRUE(IsLibReady());
    180   EXPECT_FALSE(GetError());
    181   EXPECT_EQ(TranslateErrors::NONE, GetErrorCode());
    182 
    183   ExecuteScript(kTranslate);
    184 
    185   EXPECT_TRUE(GetError());
    186   EXPECT_EQ(TranslateErrors::UNEXPECTED_SCRIPT_ERROR, GetErrorCode());
    187 }
    188 
    189 // Test if onTranslateProgress callback handles boolean type error correctly.
    190 // Remove this test once server side changes the API to return a number.
    191 TEST_F(TranslateScriptBrowserTest, CallbackGetBooleanError) {
    192   ExecuteScript(kCallbackReturnBooleanError);
    193 
    194   InjectElementLibrary();
    195   EXPECT_TRUE(IsLibReady());
    196   EXPECT_FALSE(GetError());
    197   EXPECT_EQ(TranslateErrors::NONE, GetErrorCode());
    198 
    199   ExecuteScript(kTranslate);
    200 
    201   EXPECT_TRUE(GetError());
    202   EXPECT_EQ(TranslateErrors::TRANSLATION_ERROR, GetErrorCode());
    203 }
    204 
    205 // Test if onTranslateProgress callback handles number type error correctly and
    206 // converts it to the proper error code.
    207 TEST_F(TranslateScriptBrowserTest, CallbackGetNumberError1) {
    208   ExecuteScript(kCallbackReturnNumberError);
    209   ExecuteScript(GenerateSetCallbackErrorCodeScript(1));
    210 
    211   InjectElementLibrary();
    212   EXPECT_TRUE(IsLibReady());
    213   EXPECT_FALSE(GetError());
    214   EXPECT_EQ(TranslateErrors::NONE, GetErrorCode());
    215 
    216   ExecuteScript(kTranslate);
    217 
    218   EXPECT_TRUE(GetError());
    219   EXPECT_EQ(TranslateErrors::TRANSLATION_ERROR, GetErrorCode());
    220 }
    221 
    222 // Test if onTranslateProgress callback handles number type error correctly and
    223 // converts it to the proper error code.
    224 TEST_F(TranslateScriptBrowserTest, CallbackGetNumberError2) {
    225   ExecuteScript(kCallbackReturnNumberError);
    226   ExecuteScript(GenerateSetCallbackErrorCodeScript(2));
    227 
    228   InjectElementLibrary();
    229   EXPECT_TRUE(IsLibReady());
    230   EXPECT_FALSE(GetError());
    231   EXPECT_EQ(TranslateErrors::NONE, GetErrorCode());
    232 
    233   ExecuteScript(kTranslate);
    234 
    235   EXPECT_TRUE(GetError());
    236   EXPECT_EQ(TranslateErrors::UNSUPPORTED_LANGUAGE, GetErrorCode());
    237 }
    238 
    239 // TODO(toyoshim): Add test for onLoadJavaScript.
    240