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

Unified Diff: ios/chrome/browser/translate/js_language_detection_manager_unittest.mm

Issue 2585233003: Upstream Chrome on iOS source code [2/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
« no previous file with comments | « ios/chrome/browser/test/perf_test_with_bvc_ios.mm ('k') | ios/chrome/browser/translate/translate_egtest.mm » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ios/chrome/browser/translate/js_language_detection_manager_unittest.mm
diff --git a/ios/chrome/browser/translate/js_language_detection_manager_unittest.mm b/ios/chrome/browser/translate/js_language_detection_manager_unittest.mm
new file mode 100644
index 0000000000000000000000000000000000000000..c506eb8ea4983e34168d8db544af3da161d3520c
--- /dev/null
+++ b/ios/chrome/browser/translate/js_language_detection_manager_unittest.mm
@@ -0,0 +1,351 @@
+// Copyright 2013 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 "components/translate/ios/browser/js_language_detection_manager.h"
+
+#include <string.h>
+
+#include "base/bind.h"
+#include "base/mac/scoped_nsobject.h"
+#include "base/memory/scoped_vector.h"
+#import "base/test/ios/wait_util.h"
+#include "base/values.h"
+#import "ios/chrome/browser/web/chrome_web_test.h"
+#include "ios/chrome/common/string_util.h"
+#import "ios/web/public/test/js_test_util.h"
+#import "ios/web/public/web_state/js/crw_js_injection_receiver.h"
+#import "ios/web/public/web_state/web_state.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gtest_mac.h"
+
+namespace {
+
+const char kExpectedLanguage[] = "Foo";
+
+// Returns an NSString filled with the char 'a' of length |length|.
+NSString* GetLongString(NSUInteger length) {
+ base::scoped_nsobject<NSMutableData> data(
+ [[NSMutableData alloc] initWithLength:length]);
+ memset([data mutableBytes], 'a', length);
+ NSString* long_string =
+ [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
+ return [long_string autorelease];
+}
+
+} // namespace
+
+// TODO(shreyasv): Moved this to the translate component.
+// Test fixture to test language detection.
+class JsLanguageDetectionManagerTest : public ChromeWebTest {
+ protected:
+ void SetUp() override {
+ ChromeWebTest::SetUp();
+ manager_.reset(static_cast<JsLanguageDetectionManager*>(
+ [[web_state()->GetJSInjectionReceiver()
+ instanceOfClass:[JsLanguageDetectionManager class]] retain]));
+ ASSERT_TRUE(manager_);
+ }
+
+ void LoadHtmlAndInject(NSString* html) {
+ ChromeWebTest::LoadHtml(html);
+ [manager_ inject];
+ ASSERT_TRUE([manager_ hasBeenInjected]);
+ }
+
+ // Injects JS, waits for the completion handler and verifies if the result
+ // was what was expected.
+ void InjectJsAndVerify(NSString* js, id expected_result) {
+ EXPECT_NSEQ(expected_result, web::ExecuteJavaScript(manager_, js));
+ }
+
+ // Injects JS, and spins the run loop until |condition| block returns true
+ void InjectJSAndWaitUntilCondition(NSString* js, ConditionBlock condition) {
+ [manager_ executeJavaScript:js completionHandler:nil];
+ base::test::ios::WaitUntilCondition(^bool() {
+ return condition();
+ });
+ }
+
+ // Verifies if translation was allowed or not on the page based on
+ // |expected_value|.
+ void ExpectTranslationAllowed(BOOL expected_value) {
+ InjectJsAndVerify(@"__gCrWeb.languageDetection.translationAllowed();",
+ @(expected_value));
+ }
+
+ // Verifies if |lang| attribute of the HTML tag is the |expected_html_lang|,
+ void ExpectHtmlLang(NSString* expected_html_lang) {
+ InjectJsAndVerify(@"document.documentElement.lang;", expected_html_lang);
+ }
+
+ // Verifies if the value of the |Content-Language| meta tag is the same as
+ // |expected_http_content_language|.
+ void ExpectHttpContentLanguage(NSString* expected_http_content_language) {
+ NSString* const kMetaTagContentJS =
+ @"__gCrWeb.languageDetection.getMetaContentByHttpEquiv("
+ @"'content-language');";
+ InjectJsAndVerify(kMetaTagContentJS, expected_http_content_language);
+ }
+
+ // Verifies if |__gCrWeb.languageDetection.getTextContent| correctly extracts
+ // the text content from an HTML page.
+ void ExpectTextContent(NSString* expected_text_content) {
+ base::scoped_nsobject<NSString> script([[NSString alloc]
+ initWithFormat:
+ @"__gCrWeb.languageDetection.getTextContent(document.body, %lu);",
+ language_detection::kMaxIndexChars]);
+ InjectJsAndVerify(script, expected_text_content);
+ }
+
+ base::scoped_nsobject<JsLanguageDetectionManager> manager_;
+};
+
+// Tests that |hasBeenInjected| returns YES after |inject| call.
+TEST_F(JsLanguageDetectionManagerTest, InitAndInject) {
+ LoadHtmlAndInject(@"<html></html>");
+}
+
+// Tests |__gCrWeb.languageDetection.translationAllowed| JS call.
+TEST_F(JsLanguageDetectionManagerTest, IsTranslationAllowed) {
+ LoadHtmlAndInject(@"<html></html>");
+ ExpectTranslationAllowed(YES);
+
+ LoadHtmlAndInject(@"<html><head>"
+ "<meta name='google' content='notranslate'>"
+ "</head></html>");
+ ExpectTranslationAllowed(NO);
+
+ LoadHtmlAndInject(@"<html><head>"
+ "<meta name='google' value='notranslate'>"
+ "</head></html>");
+ ExpectTranslationAllowed(NO);
+}
+
+// Tests correctness of |document.documentElement.lang| attribute.
+TEST_F(JsLanguageDetectionManagerTest, HtmlLang) {
+ base::scoped_nsobject<NSString> html;
+ // Non-empty attribute.
+ html.reset([[NSString alloc]
+ initWithFormat:@"<html lang='%s'></html>", kExpectedLanguage]);
+ LoadHtmlAndInject(html);
+ ExpectHtmlLang(@(kExpectedLanguage));
+
+ // Empty attribute.
+ LoadHtmlAndInject(@"<html></html>");
+ ExpectHtmlLang(@"");
+
+ // Test with mixed case.
+ html.reset([[NSString alloc]
+ initWithFormat:@"<html lAnG='%s'></html>", kExpectedLanguage]);
+ LoadHtmlAndInject(html);
+ ExpectHtmlLang(@(kExpectedLanguage));
+}
+
+// Tests |__gCrWeb.languageDetection.getMetaContentByHttpEquiv| JS call.
+TEST_F(JsLanguageDetectionManagerTest, HttpContentLanguage) {
+ // No content language.
+ LoadHtmlAndInject(@"<html></html>");
+ ExpectHttpContentLanguage(@"");
+ base::scoped_nsobject<NSString> html;
+
+ // Some content language.
+ html.reset(([[NSString alloc]
+ initWithFormat:@"<html><head>"
+ "<meta http-equiv='content-language' content='%s'>"
+ "</head></html>",
+ kExpectedLanguage]));
+ LoadHtmlAndInject(html);
+ ExpectHttpContentLanguage(@(kExpectedLanguage));
+
+ // Test with mixed case.
+ html.reset(([[NSString alloc]
+ initWithFormat:@"<html><head>"
+ "<meta http-equiv='cOnTenT-lAngUAge' content='%s'>"
+ "</head></html>",
+ kExpectedLanguage]));
+ LoadHtmlAndInject(html);
+ ExpectHttpContentLanguage(@(kExpectedLanguage));
+}
+
+// Tests |__gCrWeb.languageDetection.getTextContent| JS call.
+TEST_F(JsLanguageDetectionManagerTest, ExtractTextContent) {
+ LoadHtmlAndInject(@"<html><body>"
+ "<script>var text = 'No scripts!'</script>"
+ "<p style='display: none;'>Not displayed!</p>"
+ "<p style='visibility: hidden;'>Hidden!</p>"
+ "<div>Some <span>text here <b>and</b></span> there.</div>"
+ "</body></html>");
+
+ ExpectTextContent(@"\nSome text here and there.");
+}
+
+// Tests that |__gCrWeb.languageDetection.getTextContent| correctly truncates
+// text.
+TEST_F(JsLanguageDetectionManagerTest, Truncation) {
+ LoadHtmlAndInject(@"<html><body>"
+ "<script>var text = 'No scripts!'</script>"
+ "<p style='display: none;'>Not displayed!</p>"
+ "<p style='visibility: hidden;'>Hidden!</p>"
+ "<div>Some <span>text here <b>and</b></span> there.</div>"
+ "</body></html>");
+ NSString* const kTextContentJS =
+ @"__gCrWeb.languageDetection.getTextContent(document.body, 13)";
+ InjectJsAndVerify(kTextContentJS, @"\nSome text he");
+}
+
+// HTML elements introduce a line break, except inline ones.
+TEST_F(JsLanguageDetectionManagerTest, ExtractWhitespace) {
+ // |b| and |span| do not break lines.
+ // |br| and |div| do.
+ LoadHtmlAndInject(@"<html><body>"
+ "O<b>n</b>e<br>Two\tT<span>hr</span>ee<div>Four</div>"
+ "</body></html>");
+ ExpectTextContent(@"One\nTwo\tThree\nFour");
+
+ // |a| does not break lines.
+ // |li|, |p| and |ul| do.
+ LoadHtmlAndInject(
+ @"<html><body>"
+ "<ul><li>One</li><li>T<a href='foo'>wo</a></li></ul><p>Three</p>"
+ "</body></html>");
+ ExpectTextContent(@"\n\nOne\nTwo\nThree");
+}
+
+// Tests that |__gCrWeb.languageDetection.getTextContent| returns only until the
+// kMaxIndexChars number of characters even if the text content is very large.
+TEST_F(JsLanguageDetectionManagerTest, LongTextContent) {
+ // Very long string.
+ NSUInteger kLongStringLength = language_detection::kMaxIndexChars - 5;
+ base::scoped_nsobject<NSMutableString> long_string(
+ [GetLongString(kLongStringLength) mutableCopy]);
+ [long_string appendString:@" b cdefghijklmnopqrstuvwxyz"];
+
+ // The string should be cut at the last whitespace, after the 'b' character.
+ base::scoped_nsobject<NSString> html([[NSString alloc]
+ initWithFormat:@"<html><body>%@</html></body>", long_string.get()]);
+ LoadHtmlAndInject(html);
+
+ base::scoped_nsobject<NSString> script([[NSString alloc]
+ initWithFormat:
+ @"__gCrWeb.languageDetection.getTextContent(document.body, %lu);",
+ language_detection::kMaxIndexChars]);
+ NSString* result = web::ExecuteJavaScript(manager_, script);
+ EXPECT_EQ(language_detection::kMaxIndexChars, [result length]);
+}
+
+// Tests if |__gCrWeb.languageDetection.retrieveBufferedTextContent| correctly
+// retrieves the cache and then purges it.
+TEST_F(JsLanguageDetectionManagerTest, RetrieveBufferedTextContent) {
+ LoadHtmlAndInject(@"<html></html>");
+ // Set some cached text content.
+ [manager_ executeJavaScript:
+ @"__gCrWeb.languageDetection.bufferedTextContent = 'foo'"
+ completionHandler:nil];
+ [manager_ executeJavaScript:@"__gCrWeb.languageDetection.activeRequests = 1"
+ completionHandler:nil];
+ NSString* const kRetrieveBufferedTextContentJS =
+ @"__gCrWeb.languageDetection.retrieveBufferedTextContent()";
+ InjectJsAndVerify(kRetrieveBufferedTextContentJS, @"foo");
+
+ // Verify cache is purged.
+ InjectJsAndVerify(@"__gCrWeb.languageDetection.bufferedTextContent",
+ [NSNull null]);
+}
+
+// Test fixture to test |__gCrWeb.languageDetection.detectLanguage|.
+class JsLanguageDetectionManagerDetectLanguageTest
+ : public JsLanguageDetectionManagerTest {
+ public:
+ void SetUp() override {
+ JsLanguageDetectionManagerTest::SetUp();
+ auto callback = base::Bind(
+ &JsLanguageDetectionManagerDetectLanguageTest::CommandReceived,
+ base::Unretained(this));
+ web_state()->AddScriptCommandCallback(callback, "languageDetection");
+ }
+ void TearDown() override {
+ web_state()->RemoveScriptCommandCallback("languageDetection");
+ JsLanguageDetectionManagerTest::TearDown();
+ }
+ // Called when "languageDetection" command is received.
+ bool CommandReceived(const base::DictionaryValue& command,
+ const GURL&,
+ bool) {
+ commands_received_.push_back(command.DeepCopy());
+ return true;
+ }
+
+ protected:
+ // Received "languageDetection" commands.
+ ScopedVector<base::DictionaryValue> commands_received_;
+};
+
+// Tests if |__gCrWeb.languageDetection.detectLanguage| correctly informs the
+// native side when translation is not allowed.
+TEST_F(JsLanguageDetectionManagerDetectLanguageTest,
+ DetectLanguageTranslationNotAllowed) {
+ LoadHtmlAndInject(@"<html></html>");
+ [manager_ startLanguageDetection];
+ // Wait until the original injection has recived a command.
+ base::test::ios::WaitUntilCondition(^bool() {
+ return !commands_received_.empty();
+ });
+ ASSERT_EQ(1U, commands_received_.size());
+
+ commands_received_.clear();
+
+ // Stub out translationAllowed.
+ NSString* const kTranslationAllowedJS =
+ @"__gCrWeb.languageDetection.translationAllowed = function() {"
+ @" return false;"
+ @"}";
+ [manager_ executeJavaScript:kTranslationAllowedJS completionHandler:nil];
+ ConditionBlock commands_recieved_block = ^bool {
+ return commands_received_.size();
+ };
+ InjectJSAndWaitUntilCondition(@"__gCrWeb.languageDetection.detectLanguage()",
+ commands_recieved_block);
+ ASSERT_EQ(1U, commands_received_.size());
+ base::DictionaryValue* value = commands_received_[0];
+ EXPECT_TRUE(value->HasKey("translationAllowed"));
+ bool translation_allowed = true;
+ value->GetBoolean("translationAllowed", &translation_allowed);
+ EXPECT_FALSE(translation_allowed);
+}
+
+// Tests if |__gCrWeb.languageDetection.detectLanguage| correctly informs the
+// native side when translation is allowed with the right parameters.
+TEST_F(JsLanguageDetectionManagerDetectLanguageTest,
+ DetectLanguageTranslationAllowed) {
+ // A simple page that allows translation.
+ NSString* html = @"<html><head>"
+ @"<meta http-equiv='content-language' content='en'>"
+ @"</head></html>";
+ LoadHtmlAndInject(html);
+ [manager_ startLanguageDetection];
+ // Wait until the original injection has recived a command.
+ base::test::ios::WaitUntilCondition(^bool() {
+ return !commands_received_.empty();
+ });
+ ASSERT_EQ(1U, commands_received_.size());
+
+ commands_received_.clear();
+
+ [manager_ executeJavaScript:@"__gCrWeb.languageDetection.detectLanguage()"
+ completionHandler:nil];
+ base::test::ios::WaitUntilCondition(^bool() {
+ return !commands_received_.empty();
+ });
+ ASSERT_EQ(1U, commands_received_.size());
+ base::DictionaryValue* value = commands_received_[0];
+
+ EXPECT_TRUE(value->HasKey("translationAllowed"));
+ EXPECT_TRUE(value->HasKey("captureTextTime"));
+ EXPECT_TRUE(value->HasKey("htmlLang"));
+ EXPECT_TRUE(value->HasKey("httpContentLanguage"));
+
+ bool translation_allowed = false;
+ value->GetBoolean("translationAllowed", &translation_allowed);
+ EXPECT_TRUE(translation_allowed);
+}
« no previous file with comments | « ios/chrome/browser/test/perf_test_with_bvc_ios.mm ('k') | ios/chrome/browser/translate/translate_egtest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698