Chromium Code Reviews| Index: ios/chrome/browser/passwords/password_controller_js_unittest.mm |
| diff --git a/ios/chrome/browser/passwords/password_controller_js_unittest.mm b/ios/chrome/browser/passwords/password_controller_js_unittest.mm |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..aac65351073780f0cef133e5d4108efabb715ed6 |
| --- /dev/null |
| +++ b/ios/chrome/browser/passwords/password_controller_js_unittest.mm |
| @@ -0,0 +1,283 @@ |
| +// 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 <Foundation/Foundation.h> |
| + |
| +#import "ios/chrome/browser/passwords/js_password_manager.h" |
| +#import "ios/web/public/test/web_js_test.h" |
| +#import "ios/web/public/test/web_test_with_web_state.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "testing/gtest_mac.h" |
| + |
| +// Unit tests for ios/chrome/browser/web/resources/password_controller.js |
| +namespace { |
| + |
| +// Text fixture to test password controller. |
| +class PasswordControllerJsTest |
| + : public web::WebJsTest<web::WebTestWithWebState> { |
| + public: |
| + PasswordControllerJsTest() |
| + : web::WebJsTest<web::WebTestWithWebState>(@[ @"password_controller" ]) {} |
| +}; |
| + |
| +// IDs used in the Username and Password <input> elements. |
| +NSString* const kEmailInputID = @"Email"; |
| +NSString* const kPasswordInputID = @"Passwd"; |
| + |
| +// Returns an autoreleased string of an HTML form that is similar to the |
| +// Google Accounts sign in form. |email| may be nil if the form does not |
| +// need to be pre-filled with the username. Use |isReadOnly| flag to indicate |
| +// if the email field should be read-only. |
| +NSString* GAIASignInForm(NSString* formAction, |
| + NSString* email, |
| + BOOL isReadOnly) { |
| + return [NSString |
| + stringWithFormat: |
| + @"<html><body>" |
| + "<form novalidate method=\"post\" action=\"%@\" " |
| + "id=\"gaia_loginform\">" |
| + " <input name=\"GALX\" type=\"hidden\" value=\"abcdefghij\">" |
| + " <input name=\"service\" type=\"hidden\" value=\"mail\">" |
| + " <input id=\"%@\" name=\"Email\" type=\"email\" value=\"%@\" %@>" |
| + " <input id=\"%@\" name=\"Passwd\" type=\"password\" " |
| + " placeholder=\"Password\">" |
| + "</form></body></html>", |
| + formAction, kEmailInputID, email ? email : @"", |
| + isReadOnly ? @"readonly" : @"", kPasswordInputID]; |
| +} |
| + |
| +// Returns an autoreleased string of JSON for a parsed form. |
| +NSString* GAIASignInFormData(NSString* formAction) { |
| + return [NSString stringWithFormat:@"{" |
| + " \"action\":\"%@\"," |
| + " \"origin\":\"%@\"," |
| + " \"fields\":[" |
| + " {\"name\":\"%@\", \"value\":\"\"}," |
| + " {\"name\":\"%@\",\"value\":\"\"}" |
| + " ]" |
| + "}", |
| + formAction, formAction, kEmailInputID, |
| + kPasswordInputID]; |
| +} |
| + |
| +TEST_F(PasswordControllerJsTest, |
|
Eugene But (OOO till 7-30)
2016/07/13 22:30:31
If you understand the purpose if these tests, coul
vabr (Chromium)
2016/07/14 07:36:31
Done, this was a good exercise. :)
|
| + FillPasswordFormWithPrefilledUsername_SucceedsWhenUsernameMatches) { |
| + NSString* const formAction = @"https://accounts.google.com/ServiceLoginAuth"; |
| + NSString* const username = @"john.doe@gmail.com"; |
| + NSString* const password = @"super!secret"; |
| + LoadHtmlAndInject(GAIASignInForm(formAction, username, YES)); |
| + EXPECT_NSEQ(@"true", EvaluateJavaScriptWithFormat( |
| + @"__gCrWeb.fillPasswordForm(%@, '%@', '%@', '%@')", |
| + GAIASignInFormData(formAction), username, password, |
| + formAction)); |
| + // Verifies that the sign-in form has been filled with username/password. |
| + EvaluateJavaScriptOnElementsAndCheck(@"document.getElementById('%@').value", |
| + @[ kEmailInputID, kPasswordInputID ], |
| + @[ username, password ]); |
| +} |
| + |
| +TEST_F(PasswordControllerJsTest, |
| + FillPasswordFormWithPrefilledUsername_FailsWhenUsernameMismatched) { |
| + NSString* const formAction = @"https://accounts.google.com/ServiceLoginAuth"; |
| + NSString* const username1 = @"john.doe@gmail.com"; |
| + NSString* const username2 = @"jean.dubois@gmail.com"; |
| + NSString* const password = @"super!secret"; |
| + LoadHtmlAndInject(GAIASignInForm(formAction, username1, YES)); |
| + EXPECT_NSEQ(@"false", EvaluateJavaScriptWithFormat( |
| + @"__gCrWeb.fillPasswordForm(%@, '%@', '%@', '%@')", |
| + GAIASignInFormData(formAction), username2, password, |
| + formAction)); |
| + // Verifies that the sign-in form has not been filled. |
| + EvaluateJavaScriptOnElementsAndCheck(@"document.getElementById('%@').value", |
| + @[ kEmailInputID, kPasswordInputID ], |
| + @[ username1, @"" ]); |
| +} |
| + |
| +TEST_F(PasswordControllerJsTest, |
| + FillPasswordFormWithPrefilledUsername_SucceedsByOverridingUsername) { |
| + NSString* const formAction = @"https://accounts.google.com/ServiceLoginAuth"; |
| + NSString* const username1 = @"john.doe@gmail.com"; |
| + NSString* const username2 = @"jane.doe@gmail.com"; |
| + NSString* const password = @"super!secret"; |
| + LoadHtmlAndInject(GAIASignInForm(formAction, username1, NO)); |
| + EXPECT_NSEQ(@"true", EvaluateJavaScriptWithFormat( |
| + @"__gCrWeb.fillPasswordForm(%@, '%@', '%@', '%@')", |
| + GAIASignInFormData(formAction), username2, password, |
| + formAction)); |
| + // Verifies that the sign-in form has been filled with the new username |
| + // and password. |
| + EvaluateJavaScriptOnElementsAndCheck(@"document.getElementById('%@').value", |
| + @[ kEmailInputID, kPasswordInputID ], |
| + @[ username2, password ]); |
| +} |
| + |
| +TEST_F(PasswordControllerJsTest, |
| + FillPasswordFormWithGeneratedPassword_FailsWhenFormNotFound) { |
| + LoadHtmlAndInject(@"<html>" |
| + " <body>" |
| + " <form name=\"foo\">" |
| + " <input type=\"password\" name=\"ps\">" |
| + " </form>" |
| + " </body" |
| + "</html>"); |
| + NSString* const formName = @"bar"; |
| + NSString* const password = @"abc"; |
| + EXPECT_NSEQ(@"false", |
| + EvaluateJavaScriptWithFormat( |
| + @"__gCrWeb.fillPasswordFormWithGeneratedPassword('%@', '%@')", |
| + formName, password)); |
| +} |
| + |
| +TEST_F(PasswordControllerJsTest, |
| + FillPasswordFormWithGeneratedPassword_FailsWhenNoFieldsFilled) { |
| + LoadHtmlAndInject(@"<html>" |
| + " <body>" |
| + " <form name=\"foo\">" |
| + " <input type=\"text\" name=\"user\">" |
| + " <input type=\"submit\" name=\"go\">" |
| + " </form>" |
| + " </body" |
| + "</html>"); |
| + NSString* const formName = @"foo"; |
| + NSString* const password = @"abc"; |
| + EXPECT_NSEQ(@"false", |
| + EvaluateJavaScriptWithFormat( |
| + @"__gCrWeb.fillPasswordFormWithGeneratedPassword('%@', '%@')", |
| + formName, password)); |
| +} |
| + |
| +TEST_F(PasswordControllerJsTest, |
| + FillPasswordFormWithGeneratedPassword_SucceedsWhenFieldsFilled) { |
| + LoadHtmlAndInject(@"<html>" |
| + " <body>" |
| + " <form name=\"foo\">" |
| + " <input type=\"text\" id=\"user\" name=\"user\">" |
| + " <input type=\"password\" id=\"ps1\" name=\"ps1\">" |
| + " <input type=\"password\" id=\"ps2\" name=\"ps2\">" |
| + " <input type=\"submit\" name=\"go\">" |
| + " </form>" |
| + " </body" |
| + "</html>"); |
| + NSString* const formName = @"foo"; |
| + NSString* const password = @"abc"; |
| + EXPECT_NSEQ(@"true", |
| + EvaluateJavaScriptWithFormat( |
| + @"__gCrWeb.fillPasswordFormWithGeneratedPassword('%@', '%@')", |
| + formName, password)); |
| + EXPECT_NSEQ(@"true", |
| + EvaluateJavaScriptWithFormat( |
| + @"document.getElementById('ps1').value == '%@'", password)); |
| + EXPECT_NSEQ(@"true", |
| + EvaluateJavaScriptWithFormat( |
| + @"document.getElementById('ps2').value == '%@'", password)); |
| + EXPECT_NSEQ(@"false", |
| + EvaluateJavaScriptWithFormat( |
| + @"document.getElementById('user').value == '%@'", password)); |
| +} |
| + |
| +TEST_F(PasswordControllerJsTest, |
| + FindAndPreparePasswordFormsSingleFrameSingleForm) { |
| + LoadHtmlAndInject( |
| + @"<html><body>" |
| + "<form action='/generic_submit' method='post' name='login_form'>" |
| + " Name: <input type='text' name='name'>" |
| + " Password: <input type='password' name='password'>" |
| + " <input type='submit' value='Submit'>" |
| + "</form>" |
| + "</body></html>"); |
| + |
| + const std::string base_url = BaseUrl(); |
| + NSString* result = [NSString |
| + stringWithFormat: |
| + @"[{\"action\":\"/generic_submit\"," |
| + "\"method\":\"post\"," |
| + "\"name\":\"login_form\"," |
| + "\"origin\":\"%s\"," |
| + "\"fields\":[{\"element\":\"name\",\"type\":\"text\"}," |
| + "{\"element\":\"password\",\"type\":\"password\"}," |
| + "{\"element\":\"\",\"type\":\"submit\"}]," |
| + "\"usernameElement\":\"name\"," |
| + "\"usernameValue\":\"\"," |
| + "\"passwords\":[{\"element\":\"password\",\"value\":\"\"}]}]", |
| + base_url.c_str()]; |
| + EXPECT_NSEQ(result, |
| + EvaluateJavaScriptWithFormat(@"__gCrWeb.findPasswordForms()")); |
| +}; |
| + |
| +TEST_F(PasswordControllerJsTest, |
| + FindAndPreparePasswordFormsSingleFrameMultipleForms) { |
| + LoadHtmlAndInject( |
| + @"<html><body>" |
| + "<form action='/generic_submit' method='post' id='login_form1'>" |
| + " Name: <input type='text' name='name'>" |
| + " Password: <input type='password' name='password'>" |
| + " <input type='submit' value='Submit'>" |
| + "</form>" |
| + "<form action='/generic_s2' method='post' name='login_form2'>" |
| + " Name: <input type='text' name='name2'>" |
| + " Password: <input type='password' name='password2'>" |
| + " <input type='submit' value='Submit'>" |
| + "</form>" |
| + "</body></html>"); |
| + |
| + const std::string base_url = BaseUrl(); |
| + NSString* result = [NSString |
| + stringWithFormat: |
| + @"[{\"action\":\"/generic_submit\"," |
| + "\"method\":\"post\"," |
| + "\"name\":\"login_form1\"," |
| + "\"origin\":\"%s\"," |
| + "\"fields\":[{\"element\":\"name\",\"type\":\"text\"}," |
| + "{\"element\":\"password\",\"type\":\"password\"}," |
| + "{\"element\":\"\",\"type\":\"submit\"}]," |
| + "\"usernameElement\":\"name\"," |
| + "\"usernameValue\":\"\"," |
| + "\"passwords\":[{\"element\":\"password\",\"value\":\"\"}]}," |
| + "{\"action\":\"/generic_s2\"," |
| + "\"method\":\"post\"," |
| + "\"name\":\"login_form2\"," |
| + "\"origin\":\"%s\"," |
| + "\"fields\":[{\"element\":\"name2\",\"type\":\"text\"}," |
| + "{\"element\":\"password2\",\"type\":\"password\"}," |
| + "{\"element\":\"\",\"type\":\"submit\"}]," |
| + "\"usernameElement\":\"name2\"," |
| + "\"usernameValue\":\"\"," |
| + "\"passwords\":[{\"element\":\"password2\",\"value\":\"\"}]}]", |
| + base_url.c_str(), base_url.c_str()]; |
| + EXPECT_NSEQ(result, |
| + EvaluateJavaScriptWithFormat(@"__gCrWeb.findPasswordForms()")); |
| +}; |
| + |
| +TEST_F(PasswordControllerJsTest, GetPasswordFormData) { |
| + LoadHtmlAndInject( |
| + @"<html><body>" |
| + "<form name='np' id='np1' action='/generic_submit' method='post'>" |
| + " Name: <input type='text' name='name'>" |
| + " Password: <input type='password' name='password'>" |
| + " <input type='submit' value='Submit'>" |
| + "</form>" |
| + "</body></html>"); |
| + |
| + const std::string base_url = BaseUrl(); |
| + NSString* parameter = @"window.document.getElementsByTagName('form')[0]"; |
| + NSString* result = [NSString |
| + stringWithFormat: |
| + @"{\"action\":\"/generic_submit\"," |
| + "\"method\":\"post\"," |
| + "\"name\":\"np\"," |
| + "\"origin\":\"%s\"," |
| + "\"fields\":[{\"element\":\"name\",\"type\":\"text\"}," |
| + "{\"element\":\"password\",\"type\":\"password\"}," |
| + "{\"element\":\"\",\"type\":\"submit\"}]," |
| + "\"usernameElement\":\"name\"," |
| + "\"usernameValue\":\"\"," |
| + "\"passwords\":[{\"element\":\"password\",\"value\":\"\"}]}", |
| + base_url.c_str()]; |
| + EXPECT_NSEQ( |
| + result, |
| + EvaluateJavaScriptWithFormat( |
| + @"__gCrWeb.stringify(__gCrWeb.getPasswordFormData(%@))", parameter)); |
| +}; |
| + |
| +} // namespace |