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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
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 #import "components/translate/ios/browser/js_language_detection_manager.h"
6
7 #include <string.h>
8
9 #include "base/bind.h"
10 #include "base/mac/scoped_nsobject.h"
11 #include "base/memory/scoped_vector.h"
12 #import "base/test/ios/wait_util.h"
13 #include "base/values.h"
14 #import "ios/chrome/browser/web/chrome_web_test.h"
15 #include "ios/chrome/common/string_util.h"
16 #import "ios/web/public/test/js_test_util.h"
17 #import "ios/web/public/web_state/js/crw_js_injection_receiver.h"
18 #import "ios/web/public/web_state/web_state.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "testing/gtest_mac.h"
21
22 namespace {
23
24 const char kExpectedLanguage[] = "Foo";
25
26 // Returns an NSString filled with the char 'a' of length |length|.
27 NSString* GetLongString(NSUInteger length) {
28 base::scoped_nsobject<NSMutableData> data(
29 [[NSMutableData alloc] initWithLength:length]);
30 memset([data mutableBytes], 'a', length);
31 NSString* long_string =
32 [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
33 return [long_string autorelease];
34 }
35
36 } // namespace
37
38 // TODO(shreyasv): Moved this to the translate component.
39 // Test fixture to test language detection.
40 class JsLanguageDetectionManagerTest : public ChromeWebTest {
41 protected:
42 void SetUp() override {
43 ChromeWebTest::SetUp();
44 manager_.reset(static_cast<JsLanguageDetectionManager*>(
45 [[web_state()->GetJSInjectionReceiver()
46 instanceOfClass:[JsLanguageDetectionManager class]] retain]));
47 ASSERT_TRUE(manager_);
48 }
49
50 void LoadHtmlAndInject(NSString* html) {
51 ChromeWebTest::LoadHtml(html);
52 [manager_ inject];
53 ASSERT_TRUE([manager_ hasBeenInjected]);
54 }
55
56 // Injects JS, waits for the completion handler and verifies if the result
57 // was what was expected.
58 void InjectJsAndVerify(NSString* js, id expected_result) {
59 EXPECT_NSEQ(expected_result, web::ExecuteJavaScript(manager_, js));
60 }
61
62 // Injects JS, and spins the run loop until |condition| block returns true
63 void InjectJSAndWaitUntilCondition(NSString* js, ConditionBlock condition) {
64 [manager_ executeJavaScript:js completionHandler:nil];
65 base::test::ios::WaitUntilCondition(^bool() {
66 return condition();
67 });
68 }
69
70 // Verifies if translation was allowed or not on the page based on
71 // |expected_value|.
72 void ExpectTranslationAllowed(BOOL expected_value) {
73 InjectJsAndVerify(@"__gCrWeb.languageDetection.translationAllowed();",
74 @(expected_value));
75 }
76
77 // Verifies if |lang| attribute of the HTML tag is the |expected_html_lang|,
78 void ExpectHtmlLang(NSString* expected_html_lang) {
79 InjectJsAndVerify(@"document.documentElement.lang;", expected_html_lang);
80 }
81
82 // Verifies if the value of the |Content-Language| meta tag is the same as
83 // |expected_http_content_language|.
84 void ExpectHttpContentLanguage(NSString* expected_http_content_language) {
85 NSString* const kMetaTagContentJS =
86 @"__gCrWeb.languageDetection.getMetaContentByHttpEquiv("
87 @"'content-language');";
88 InjectJsAndVerify(kMetaTagContentJS, expected_http_content_language);
89 }
90
91 // Verifies if |__gCrWeb.languageDetection.getTextContent| correctly extracts
92 // the text content from an HTML page.
93 void ExpectTextContent(NSString* expected_text_content) {
94 base::scoped_nsobject<NSString> script([[NSString alloc]
95 initWithFormat:
96 @"__gCrWeb.languageDetection.getTextContent(document.body, %lu);",
97 language_detection::kMaxIndexChars]);
98 InjectJsAndVerify(script, expected_text_content);
99 }
100
101 base::scoped_nsobject<JsLanguageDetectionManager> manager_;
102 };
103
104 // Tests that |hasBeenInjected| returns YES after |inject| call.
105 TEST_F(JsLanguageDetectionManagerTest, InitAndInject) {
106 LoadHtmlAndInject(@"<html></html>");
107 }
108
109 // Tests |__gCrWeb.languageDetection.translationAllowed| JS call.
110 TEST_F(JsLanguageDetectionManagerTest, IsTranslationAllowed) {
111 LoadHtmlAndInject(@"<html></html>");
112 ExpectTranslationAllowed(YES);
113
114 LoadHtmlAndInject(@"<html><head>"
115 "<meta name='google' content='notranslate'>"
116 "</head></html>");
117 ExpectTranslationAllowed(NO);
118
119 LoadHtmlAndInject(@"<html><head>"
120 "<meta name='google' value='notranslate'>"
121 "</head></html>");
122 ExpectTranslationAllowed(NO);
123 }
124
125 // Tests correctness of |document.documentElement.lang| attribute.
126 TEST_F(JsLanguageDetectionManagerTest, HtmlLang) {
127 base::scoped_nsobject<NSString> html;
128 // Non-empty attribute.
129 html.reset([[NSString alloc]
130 initWithFormat:@"<html lang='%s'></html>", kExpectedLanguage]);
131 LoadHtmlAndInject(html);
132 ExpectHtmlLang(@(kExpectedLanguage));
133
134 // Empty attribute.
135 LoadHtmlAndInject(@"<html></html>");
136 ExpectHtmlLang(@"");
137
138 // Test with mixed case.
139 html.reset([[NSString alloc]
140 initWithFormat:@"<html lAnG='%s'></html>", kExpectedLanguage]);
141 LoadHtmlAndInject(html);
142 ExpectHtmlLang(@(kExpectedLanguage));
143 }
144
145 // Tests |__gCrWeb.languageDetection.getMetaContentByHttpEquiv| JS call.
146 TEST_F(JsLanguageDetectionManagerTest, HttpContentLanguage) {
147 // No content language.
148 LoadHtmlAndInject(@"<html></html>");
149 ExpectHttpContentLanguage(@"");
150 base::scoped_nsobject<NSString> html;
151
152 // Some content language.
153 html.reset(([[NSString alloc]
154 initWithFormat:@"<html><head>"
155 "<meta http-equiv='content-language' content='%s'>"
156 "</head></html>",
157 kExpectedLanguage]));
158 LoadHtmlAndInject(html);
159 ExpectHttpContentLanguage(@(kExpectedLanguage));
160
161 // Test with mixed case.
162 html.reset(([[NSString alloc]
163 initWithFormat:@"<html><head>"
164 "<meta http-equiv='cOnTenT-lAngUAge' content='%s'>"
165 "</head></html>",
166 kExpectedLanguage]));
167 LoadHtmlAndInject(html);
168 ExpectHttpContentLanguage(@(kExpectedLanguage));
169 }
170
171 // Tests |__gCrWeb.languageDetection.getTextContent| JS call.
172 TEST_F(JsLanguageDetectionManagerTest, ExtractTextContent) {
173 LoadHtmlAndInject(@"<html><body>"
174 "<script>var text = 'No scripts!'</script>"
175 "<p style='display: none;'>Not displayed!</p>"
176 "<p style='visibility: hidden;'>Hidden!</p>"
177 "<div>Some <span>text here <b>and</b></span> there.</div>"
178 "</body></html>");
179
180 ExpectTextContent(@"\nSome text here and there.");
181 }
182
183 // Tests that |__gCrWeb.languageDetection.getTextContent| correctly truncates
184 // text.
185 TEST_F(JsLanguageDetectionManagerTest, Truncation) {
186 LoadHtmlAndInject(@"<html><body>"
187 "<script>var text = 'No scripts!'</script>"
188 "<p style='display: none;'>Not displayed!</p>"
189 "<p style='visibility: hidden;'>Hidden!</p>"
190 "<div>Some <span>text here <b>and</b></span> there.</div>"
191 "</body></html>");
192 NSString* const kTextContentJS =
193 @"__gCrWeb.languageDetection.getTextContent(document.body, 13)";
194 InjectJsAndVerify(kTextContentJS, @"\nSome text he");
195 }
196
197 // HTML elements introduce a line break, except inline ones.
198 TEST_F(JsLanguageDetectionManagerTest, ExtractWhitespace) {
199 // |b| and |span| do not break lines.
200 // |br| and |div| do.
201 LoadHtmlAndInject(@"<html><body>"
202 "O<b>n</b>e<br>Two\tT<span>hr</span>ee<div>Four</div>"
203 "</body></html>");
204 ExpectTextContent(@"One\nTwo\tThree\nFour");
205
206 // |a| does not break lines.
207 // |li|, |p| and |ul| do.
208 LoadHtmlAndInject(
209 @"<html><body>"
210 "<ul><li>One</li><li>T<a href='foo'>wo</a></li></ul><p>Three</p>"
211 "</body></html>");
212 ExpectTextContent(@"\n\nOne\nTwo\nThree");
213 }
214
215 // Tests that |__gCrWeb.languageDetection.getTextContent| returns only until the
216 // kMaxIndexChars number of characters even if the text content is very large.
217 TEST_F(JsLanguageDetectionManagerTest, LongTextContent) {
218 // Very long string.
219 NSUInteger kLongStringLength = language_detection::kMaxIndexChars - 5;
220 base::scoped_nsobject<NSMutableString> long_string(
221 [GetLongString(kLongStringLength) mutableCopy]);
222 [long_string appendString:@" b cdefghijklmnopqrstuvwxyz"];
223
224 // The string should be cut at the last whitespace, after the 'b' character.
225 base::scoped_nsobject<NSString> html([[NSString alloc]
226 initWithFormat:@"<html><body>%@</html></body>", long_string.get()]);
227 LoadHtmlAndInject(html);
228
229 base::scoped_nsobject<NSString> script([[NSString alloc]
230 initWithFormat:
231 @"__gCrWeb.languageDetection.getTextContent(document.body, %lu);",
232 language_detection::kMaxIndexChars]);
233 NSString* result = web::ExecuteJavaScript(manager_, script);
234 EXPECT_EQ(language_detection::kMaxIndexChars, [result length]);
235 }
236
237 // Tests if |__gCrWeb.languageDetection.retrieveBufferedTextContent| correctly
238 // retrieves the cache and then purges it.
239 TEST_F(JsLanguageDetectionManagerTest, RetrieveBufferedTextContent) {
240 LoadHtmlAndInject(@"<html></html>");
241 // Set some cached text content.
242 [manager_ executeJavaScript:
243 @"__gCrWeb.languageDetection.bufferedTextContent = 'foo'"
244 completionHandler:nil];
245 [manager_ executeJavaScript:@"__gCrWeb.languageDetection.activeRequests = 1"
246 completionHandler:nil];
247 NSString* const kRetrieveBufferedTextContentJS =
248 @"__gCrWeb.languageDetection.retrieveBufferedTextContent()";
249 InjectJsAndVerify(kRetrieveBufferedTextContentJS, @"foo");
250
251 // Verify cache is purged.
252 InjectJsAndVerify(@"__gCrWeb.languageDetection.bufferedTextContent",
253 [NSNull null]);
254 }
255
256 // Test fixture to test |__gCrWeb.languageDetection.detectLanguage|.
257 class JsLanguageDetectionManagerDetectLanguageTest
258 : public JsLanguageDetectionManagerTest {
259 public:
260 void SetUp() override {
261 JsLanguageDetectionManagerTest::SetUp();
262 auto callback = base::Bind(
263 &JsLanguageDetectionManagerDetectLanguageTest::CommandReceived,
264 base::Unretained(this));
265 web_state()->AddScriptCommandCallback(callback, "languageDetection");
266 }
267 void TearDown() override {
268 web_state()->RemoveScriptCommandCallback("languageDetection");
269 JsLanguageDetectionManagerTest::TearDown();
270 }
271 // Called when "languageDetection" command is received.
272 bool CommandReceived(const base::DictionaryValue& command,
273 const GURL&,
274 bool) {
275 commands_received_.push_back(command.DeepCopy());
276 return true;
277 }
278
279 protected:
280 // Received "languageDetection" commands.
281 ScopedVector<base::DictionaryValue> commands_received_;
282 };
283
284 // Tests if |__gCrWeb.languageDetection.detectLanguage| correctly informs the
285 // native side when translation is not allowed.
286 TEST_F(JsLanguageDetectionManagerDetectLanguageTest,
287 DetectLanguageTranslationNotAllowed) {
288 LoadHtmlAndInject(@"<html></html>");
289 [manager_ startLanguageDetection];
290 // Wait until the original injection has recived a command.
291 base::test::ios::WaitUntilCondition(^bool() {
292 return !commands_received_.empty();
293 });
294 ASSERT_EQ(1U, commands_received_.size());
295
296 commands_received_.clear();
297
298 // Stub out translationAllowed.
299 NSString* const kTranslationAllowedJS =
300 @"__gCrWeb.languageDetection.translationAllowed = function() {"
301 @" return false;"
302 @"}";
303 [manager_ executeJavaScript:kTranslationAllowedJS completionHandler:nil];
304 ConditionBlock commands_recieved_block = ^bool {
305 return commands_received_.size();
306 };
307 InjectJSAndWaitUntilCondition(@"__gCrWeb.languageDetection.detectLanguage()",
308 commands_recieved_block);
309 ASSERT_EQ(1U, commands_received_.size());
310 base::DictionaryValue* value = commands_received_[0];
311 EXPECT_TRUE(value->HasKey("translationAllowed"));
312 bool translation_allowed = true;
313 value->GetBoolean("translationAllowed", &translation_allowed);
314 EXPECT_FALSE(translation_allowed);
315 }
316
317 // Tests if |__gCrWeb.languageDetection.detectLanguage| correctly informs the
318 // native side when translation is allowed with the right parameters.
319 TEST_F(JsLanguageDetectionManagerDetectLanguageTest,
320 DetectLanguageTranslationAllowed) {
321 // A simple page that allows translation.
322 NSString* html = @"<html><head>"
323 @"<meta http-equiv='content-language' content='en'>"
324 @"</head></html>";
325 LoadHtmlAndInject(html);
326 [manager_ startLanguageDetection];
327 // Wait until the original injection has recived a command.
328 base::test::ios::WaitUntilCondition(^bool() {
329 return !commands_received_.empty();
330 });
331 ASSERT_EQ(1U, commands_received_.size());
332
333 commands_received_.clear();
334
335 [manager_ executeJavaScript:@"__gCrWeb.languageDetection.detectLanguage()"
336 completionHandler:nil];
337 base::test::ios::WaitUntilCondition(^bool() {
338 return !commands_received_.empty();
339 });
340 ASSERT_EQ(1U, commands_received_.size());
341 base::DictionaryValue* value = commands_received_[0];
342
343 EXPECT_TRUE(value->HasKey("translationAllowed"));
344 EXPECT_TRUE(value->HasKey("captureTextTime"));
345 EXPECT_TRUE(value->HasKey("htmlLang"));
346 EXPECT_TRUE(value->HasKey("httpContentLanguage"));
347
348 bool translation_allowed = false;
349 value->GetBoolean("translationAllowed", &translation_allowed);
350 EXPECT_TRUE(translation_allowed);
351 }
OLDNEW
« 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