Bug 1188719 - Tests for the username fill login context menu. r=MattN

This commit is contained in:
Bernardo P. Rittmeyer
2015-08-20 11:47:21 -07:00
parent c86e3f455d
commit eed01006ac
3 changed files with 254 additions and 89 deletions

View File

@@ -80,7 +80,7 @@ function runTest(testNum) {
"context-inspect", true];
}
var passwordFillItems = [
var loginFillItems = [
"---", null,
"fill-login", null,
[
@@ -652,7 +652,8 @@ function runTest(testNum) {
"context-searchselect",true,
"---", null,
"spell-check-enabled", true
].concat(inspectItems));
].concat(loginFillItems)
.concat(inspectItems));
closeContextMenu();
selectInputText(select_inputtext_password); // Select text prior to opening context menu.
openContextMenuFor(select_inputtext_password); // Invoke context menu for next test.
@@ -675,7 +676,7 @@ function runTest(testNum) {
["spell-check-dictionary-en-US", true,
"---", null,
"spell-add-dictionaries", true], null
].concat(passwordFillItems)
].concat(loginFillItems)
.concat(inspectItems));
closeContextMenu();
subwindow.getSelection().removeAllRanges();

View File

@@ -8,6 +8,7 @@ Cu.import("resource://testing-common/LoginTestUtils.jsm", this);
// The hostname for the test URIs.
const TEST_HOSTNAME = "https://example.com";
const MULTIPLE_FORMS_PAGE_PATH = "/browser/toolkit/components/passwordmgr/test/browser/multiple_forms.html";
/**
* Initialize logins needed for the tests and disable autofill
@@ -28,13 +29,35 @@ add_task(function* test_initialize() {
* Check if the context menu is populated with the right
* menuitems for the target password input field.
*/
add_task(function* test_context_menu_populate() {
add_task(function* test_context_menu_populate_password() {
yield BrowserTestUtils.withNewTab({
gBrowser,
url: TEST_HOSTNAME + MULTIPLE_FORMS_PAGE_PATH,
}, function* (browser) {
let passwordInput = browser.contentWindow.document.getElementById("test-password-1");
yield openPasswordContextMenu(browser, passwordInput);
// Check the content of the password manager popup
let popupMenu = document.getElementById("fill-login-popup");
checkMenu(popupMenu);
let contextMenu = document.getElementById("contentAreaContextMenu");
contextMenu.hidePopup();
});
});
/**
* Check if the context menu is populated with the right menuitems
* for the target username field with a password field present.
*/
add_task(function* test_context_menu_populate_username_with_password() {
yield BrowserTestUtils.withNewTab({
gBrowser,
url: TEST_HOSTNAME + "/browser/toolkit/components/" +
"passwordmgr/test/browser/multiple_forms.html",
}, function* (browser) {
let passwordInput = browser.contentWindow.document.getElementById("test-password-1");
let passwordInput = browser.contentWindow.document.getElementById("test-username-2");
yield openPasswordContextMenu(browser, passwordInput);
@@ -52,87 +75,104 @@ add_task(function* test_context_menu_populate() {
* login menuitem is clicked.
*/
add_task(function* test_context_menu_password_fill() {
// Set of element ids to check.
let testSet = [
{
passwordInput: "test-password-1",
unchangedFields: null,
},
{
passwordInput: "test-password-2",
unchangedFields: ["test-username-2"],
},
{
passwordInput: "test-password-3",
unchangedFields: ["test-username-3"],
},
{
passwordInput: "test-password-4",
unchangedFields: ["test-username-4"],
},
{
passwordInput: "test-password-5",
unchangedFields: ["test-username-5", "test-password2-5"],
},
{
passwordInput: "test-password2-5",
unchangedFields: ["test-username-5", "test-password-5"],
},
{
passwordInput: "test-password-6",
unchangedFields: ["test-username-6", "test-password2-6"],
},
{
passwordInput: "test-password2-6",
unchangedFields: ["test-username-6", "test-password-6"],
},
{
passwordInput: "test-password-7",
unchangedFields: null,
},
];
yield BrowserTestUtils.withNewTab({
gBrowser,
url: TEST_HOSTNAME + "/browser/toolkit/components/" +
"passwordmgr/test/browser/multiple_forms.html",
url: TEST_HOSTNAME + MULTIPLE_FORMS_PAGE_PATH,
}, function* (browser) {
for (let testCase of testSet) {
let passwordInput = browser.contentWindow.document.getElementById(testCase.passwordInput);
yield openPasswordContextMenu(browser, passwordInput);
let testForms = browser.contentWindow.document.getElementsByClassName("test-form");
for (let form of testForms) {
let usernameInputList = form.querySelectorAll("input[type='password']");
info("Testing form: " + form.getAttribute("description"));
let popupMenu = document.getElementById("fill-login-popup");
for (let passwordField of usernameInputList) {
info("Testing password field: " + passwordField.id);
// Store the values of fields that should remain unchanged.
let unchangedFieldsValues = null;
if (testCase.unchangedFields) {
unchangedFieldsValues = [];
for (let fieldId of testCase.unchangedFields) {
unchangedFieldsValues[fieldId] = browser.contentWindow.document.getElementById(fieldId).value;
let contextMenu = document.getElementById("contentAreaContextMenu");
let menuItemStatus = form.getAttribute("menuitemStatus");
// Synthesize a right mouse click over the username input element.
yield openPasswordContextMenu(browser, passwordField, ()=> {
let popupHeader = document.getElementById("fill-login");
// If the password field is disabled or read-only, we want to see
// the disabled Fill Password popup header.
if (passwordField.disabled || passwordField.readOnly) {
Assert.ok(!popupHeader.hidden, "Popup menu is not hidden.");
Assert.ok(popupHeader.disabled, "Popup menu is disabled.");
contextMenu.hidePopup();
return false;
}
return true;
});
if (contextMenu.state != "open") {
continue;
}
// The only field affected by the password fill
// should be the target password field itself.
let unchangedFields = form.querySelectorAll('input:not(#' + passwordField.id + ')');
yield assertContextMenuFill(form, null, passwordField, unchangedFields);
contextMenu.hidePopup();
}
}
});
});
// Execute the default command of the first login menuitem found at the context menu.
let firstLoginItem = popupMenu.getElementsByClassName("context-login-item")[0];
firstLoginItem.doCommand();
/**
* Check if the form is correctly filled when one
* username context menu login menuitem is clicked.
*/
add_task(function* test_context_menu_username_login_fill() {
yield BrowserTestUtils.withNewTab({
gBrowser,
url: TEST_HOSTNAME + MULTIPLE_FORMS_PAGE_PATH,
}, function* (browser) {
yield BrowserTestUtils.waitForEvent(passwordInput, "input", "Password input value changed");
let testForms = browser.contentWindow.document.getElementsByClassName("test-form");
for (let form of testForms) {
let usernameInputList = form.querySelectorAll("input[type='text']");
info("Testing form: " + form.getAttribute("description"));
// Find the used login by it's username (Use only unique usernames in this test).
let login = getLoginFromUsername(firstLoginItem.label);
for (let usernameField of usernameInputList) {
info("Testing username field: " + usernameField.id);
Assert.equal(login.password, passwordInput.value, "Password filled and correct.");
// We always want to check if the first password field is filled,
// since this is the current behavior from the _fillForm function.
let passwordField = form.querySelector("input[type='password']");
// Check that the fields that should remain unchanged didn't got modified.
if (testCase.unchangedFields) {
Assert.ok(testCase.unchangedFields.every(fieldId => {
return unchangedFieldsValues[fieldId] == browser.contentWindow.document.getElementById(fieldId).value;
}), "Other fields were not changed.");
let contextMenu = document.getElementById("contentAreaContextMenu");
let menuItemStatus = form.getAttribute("menuitemStatus");
// Synthesize a right mouse click over the username input element.
yield openPasswordContextMenu(browser, usernameField, ()=> {
let popupHeader = document.getElementById("fill-login");
// If we don't want to see the actual popup menu,
// check if the popup is hidden or disabled.
if (!passwordField || usernameField.disabled || usernameField.readOnly ||
passwordField.disabled || passwordField.readOnly) {
if (!passwordField) {
Assert.ok(popupHeader.hidden, "Popup menu is hidden.");
} else {
Assert.ok(!popupHeader.hidden, "Popup menu is not hidden.");
Assert.ok(popupHeader.disabled, "Popup menu is disabled.");
}
contextMenu.hidePopup();
return false;
}
return true;
});
if (contextMenu.state != "open") {
continue;
}
// We shouldn't change any field that's not the target username field or the first password field
let unchangedFields = form.querySelectorAll('input:not(#' + usernameField.id + '):not(#' + passwordField.id + ')');
yield assertContextMenuFill(form, usernameField, passwordField, unchangedFields);
contextMenu.hidePopup();
}
let contextMenu = document.getElementById("contentAreaContextMenu");
contextMenu.hidePopup();
}
});
});
@@ -143,8 +183,7 @@ add_task(function* test_context_menu_password_fill() {
add_task(function* test_context_menu_iframe_fill() {
yield BrowserTestUtils.withNewTab({
gBrowser,
url: TEST_HOSTNAME + "/browser/toolkit/components/" +
"passwordmgr/test/browser/multiple_forms.html",
url: TEST_HOSTNAME + MULTIPLE_FORMS_PAGE_PATH,
}, function* (browser) {
let iframe = browser.contentWindow.document.getElementById("test-iframe");
let passwordInput = iframe.contentDocument.getElementById("form-basic-password");
@@ -199,14 +238,22 @@ add_task(function* test_context_menu_iframe_fill() {
/**
* Synthesize mouse clicks to open the password manager context menu popup
* for a target password input element.
*
* assertCallback should return true if we should continue or else false.
*/
function* openPasswordContextMenu(browser, passwordInput) {
function* openPasswordContextMenu(browser, passwordInput, assertCallback = null) {
// Synthesize a right mouse click over the password input element.
let contextMenuShownPromise = BrowserTestUtils.waitForEvent(window, "popupshown");
let eventDetails = {type: "contextmenu", button: 2};
BrowserTestUtils.synthesizeMouseAtCenter(passwordInput, eventDetails, browser);
yield contextMenuShownPromise;
if (assertCallback) {
if (!assertCallback.call()) {
return;
}
}
// Synthesize a mouse click over the fill login menu header.
let popupHeader = document.getElementById("fill-login");
let popupShownPromise = BrowserTestUtils.waitForEvent(popupHeader, "popupshown");
@@ -214,6 +261,51 @@ function* openPasswordContextMenu(browser, passwordInput) {
yield popupShownPromise;
}
/**
* Verify that only the expected form fields are filled.
*/
function* assertContextMenuFill(form, usernameField, passwordField, unchangedFields){
let popupMenu = document.getElementById("fill-login-popup");
// Store the value of fields that should remain unchanged.
if (unchangedFields.length) {
for (let field of unchangedFields) {
field.setAttribute("original-value", field.value);
}
}
// Execute the default command of the first login menuitem found at the context menu.
let firstLoginItem = popupMenu.getElementsByClassName("context-login-item")[0];
firstLoginItem.doCommand();
yield BrowserTestUtils.waitForEvent(form, "input", "Username input value changed");
// Find the used login by it's username (Use only unique usernames in this test).
let login = getLoginFromUsername(firstLoginItem.label);
// If we have an username field, check if it's correctly filled
if (usernameField && usernameField.getAttribute("expectedFail") == null) {
Assert.equal(login.username, usernameField.value, "Username filled and correct.");
}
// If we have a password field, check if it's correctly filled
if (passwordField && passwordField.getAttribute("expectedFail") == null) {
Assert.equal(passwordField.value, login.password, "Password filled and correct.");
}
// Check that all fields that should not change have the same value as before.
if (unchangedFields.length) {
Assert.ok(()=> {
for (let field of unchangedFields) {
if (field.value != field.getAttribute("original-value")) {
return false;
}
}
return true;
}, "Other fields were not changed.");
}
}
/**
* Check if every login that matches the page hostname are available at the context menu.
*/

View File

@@ -2,54 +2,126 @@
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<!-- Password only form -->
<form id='form-1'>
<form class="test-form"
description="Password only form">
<input id='test-password-1' type='password' name='pname' value=''>
<input type='submit'>Submit</input>
</form>
<!-- Simple username and password blank form -->
<form id='form-2'>
<form class="test-form"
description="Username only form">
<input id='test-username-1' type='text' name='uname' value=''>
<input type='submit'>Submit</input>
</form>
<form class="test-form"
description="Simple username and password blank form">
<input id='test-username-2' type='text' name='uname' value=''>
<input id='test-password-2' type='password' name='pname' value=''>
<button type='submit'>Submit</button>
</form>
<!-- Simple username and password form, prefilled username -->
<form id='form-3'>
<form class="test-form"
description="Simple username and password form, prefilled username">
<input id='test-username-3' type='text' name='uname' value='testuser'>
<input id='test-password-3' type='password' name='pname' value=''>
<button type='submit'>Submit</button>
</form>
<!-- Simple username and password form, prefilled username and password -->
<form id='form-4'>
<form class="test-form"
description="Simple username and password form, prefilled username and password">
<input id='test-username-4' type='text' name='uname' value='testuser'>
<input id='test-password-4' type='password' name='pname' value='testpass'>
<button type='submit'>Submit</button>
</form>
<!-- One username and two passwords empty form -->
<form id='form-5'>
<form class="test-form"
description="One username and two passwords empty form">
<input id='test-username-5' type='text' name='uname'>
<input id='test-password-5' type='password' name='pname'>
<input id='test-password2-5' type='password' name='pname2'>
<button type='submit'>Submit</button>
</form>
<!-- One username and two passwords form, fields prefiled -->
<form id='form-6'>
<form class="test-form"
description="One username and two passwords form, fields prefiled">
<input id='test-username-6' type='text' name='uname' value="testuser">
<input id='test-password-6' type='password' name='pname' value="testpass">
<input id='test-password2-6' type='password' name='pname2' value="testpass">
<button type='submit'>Submit</button>
</form>
<!-- Password field with no form -->
<div id='form-7'>
<div class="test-form"
description="Username and password fields with no form">
<input id='test-username-7' type='text' name='uname' value="testuser">
<input id='test-password-7' type='password' name='pname' value="testpass">
</div>
<form class="test-form"
description="Simple username and password blank form, with disabled password">
<input id='test-username-8' type='text' name='uname' value=''>
<input id='test-password-8' type='password' name='pname' value='' disabled>
<button type='submit'>Submit</button>
</form>
<form class="test-form"
description="Simple username and password blank form, with disabled username">
<input id='test-username-9' type='text' name='uname' value='' disabled>
<input id='test-password-9' type='password' name='pname' value=''>
<button type='submit'>Submit</button>
</form>
<form class="test-form"
description="Simple username and password blank form, with readonly password">
<input id='test-username-10' type='text' name='uname' value=''>
<input id='test-password-10' type='password' name='pname' value='' readonly>
<button type='submit'>Submit</button>
</form>
<form class="test-form"
description="Simple username and password blank form, with readonly username">
<input id='test-username-11' type='text' name='uname' value='' readonly>
<input id='test-password-11' type='password' name='pname' value=''>
<button type='submit'>Submit</button>
</form>
<form class="test-form"
description="Two username and one passwords form, fields prefiled">
<input id='test-username-12' type='text' name='uname' value="testuser">
<input id='test-username2-12' type='text' name='uname2' value="testuser">
<input id='test-password-12' type='password' name='pname' value="testpass">
<button type='submit'>Submit</button>
</form>
<form class="test-form"
description="Two username and one passwords form, one disabled username field">
<input id='test-username-13' type='text' name='uname'>
<input id='test-username2-13' type='text' name='uname2' disabled>
<input id='test-password-13' type='password' name='pname'>
<button type='submit'>Submit</button>
</form>
<div class="test-form"
description="Second username and password fields with no form">
<input id='test-username-14' type='text' name='uname'>
<input id='test-password-14' type='password' name='pname' expectedFail>
</div>
<!-- Form in an iframe -->
<iframe src="https://example.org/browser/toolkit/components/passwordmgr/test/browser/form_basic.html" id="test-iframe"></iframe>