mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 433238 - Tests for the password manager contextual menu password fill. r=MattN
This commit is contained in:
parent
845e03690d
commit
eee2e6e0b2
@ -61,7 +61,9 @@ function getVisibleMenuItems(aMenu, aData) {
|
|||||||
items.push("+" + label);
|
items.push("+" + label);
|
||||||
} else if (item.id.indexOf("spell-check-dictionary-") != 0 &&
|
} else if (item.id.indexOf("spell-check-dictionary-") != 0 &&
|
||||||
item.id != "spell-no-suggestions" &&
|
item.id != "spell-no-suggestions" &&
|
||||||
item.id != "spell-add-dictionaries-main") {
|
item.id != "spell-add-dictionaries-main" &&
|
||||||
|
item.id != "fill-login-saved-passwords" &&
|
||||||
|
item.id != "fill-login-no-logins") {
|
||||||
ok(key, "menuitem " + item.id + " has an access key");
|
ok(key, "menuitem " + item.id + " has an access key");
|
||||||
if (accessKeys[key])
|
if (accessKeys[key])
|
||||||
ok(false, "menuitem " + item.id + " has same accesskey as " + accessKeys[key]);
|
ok(false, "menuitem " + item.id + " has same accesskey as " + accessKeys[key]);
|
||||||
|
@ -80,6 +80,16 @@ function runTest(testNum) {
|
|||||||
"context-inspect", true];
|
"context-inspect", true];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var passwordFillItems = [
|
||||||
|
"---", null,
|
||||||
|
"fill-login", null,
|
||||||
|
[
|
||||||
|
"fill-login-no-logins", false,
|
||||||
|
"---", null,
|
||||||
|
"fill-login-saved-passwords", true
|
||||||
|
], null,
|
||||||
|
];
|
||||||
|
|
||||||
var tests = [
|
var tests = [
|
||||||
function () {
|
function () {
|
||||||
// Invoke context menu for next test.
|
// Invoke context menu for next test.
|
||||||
@ -665,7 +675,8 @@ function runTest(testNum) {
|
|||||||
["spell-check-dictionary-en-US", true,
|
["spell-check-dictionary-en-US", true,
|
||||||
"---", null,
|
"---", null,
|
||||||
"spell-add-dictionaries", true], null
|
"spell-add-dictionaries", true], null
|
||||||
].concat(inspectItems));
|
].concat(passwordFillItems)
|
||||||
|
.concat(inspectItems));
|
||||||
closeContextMenu();
|
closeContextMenu();
|
||||||
subwindow.getSelection().removeAllRanges();
|
subwindow.getSelection().removeAllRanges();
|
||||||
openContextMenuFor(plugin);
|
openContextMenuFor(plugin);
|
||||||
|
@ -167,6 +167,11 @@ function runTest(testNum) {
|
|||||||
"---", null,
|
"---", null,
|
||||||
"context-selectall", false,
|
"context-selectall", false,
|
||||||
"---", null,
|
"---", null,
|
||||||
|
"fill-login", null,
|
||||||
|
["fill-login-no-logins", false,
|
||||||
|
"---", null,
|
||||||
|
"fill-login-saved-passwords", true], null,
|
||||||
|
"---", null,
|
||||||
"context-inspect", true]);
|
"context-inspect", true]);
|
||||||
|
|
||||||
closeContextMenu();
|
closeContextMenu();
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
support-files =
|
support-files =
|
||||||
authenticate.sjs
|
authenticate.sjs
|
||||||
form_basic.html
|
form_basic.html
|
||||||
|
multiple_forms.html
|
||||||
|
|
||||||
[browser_DOMFormHasPassword.js]
|
[browser_DOMFormHasPassword.js]
|
||||||
[browser_DOMInputPasswordAdded.js]
|
[browser_DOMInputPasswordAdded.js]
|
||||||
@ -10,6 +11,7 @@ support-files =
|
|||||||
skip-if = true # Intermittent failures: Bug 1182296, bug 1148771
|
skip-if = true # Intermittent failures: Bug 1182296, bug 1148771
|
||||||
[browser_passwordmgr_editing.js]
|
[browser_passwordmgr_editing.js]
|
||||||
skip-if = os == "linux"
|
skip-if = os == "linux"
|
||||||
|
[browser_context_menu.js]
|
||||||
[browser_passwordmgr_fields.js]
|
[browser_passwordmgr_fields.js]
|
||||||
[browser_passwordmgr_observers.js]
|
[browser_passwordmgr_observers.js]
|
||||||
[browser_passwordmgr_sort.js]
|
[browser_passwordmgr_sort.js]
|
||||||
|
@ -0,0 +1,270 @@
|
|||||||
|
/*
|
||||||
|
* Test the password manager context menu.
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
Cu.import("resource://testing-common/LoginTestUtils.jsm", this);
|
||||||
|
|
||||||
|
// The hostname for the test URIs.
|
||||||
|
const TEST_HOSTNAME = "https://example.com";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize logins needed for the tests and disable autofill
|
||||||
|
* for login forms for easier testing of manual fill.
|
||||||
|
*/
|
||||||
|
add_task(function* test_initialize() {
|
||||||
|
Services.prefs.setBoolPref("signon.autofillForms", false);
|
||||||
|
registerCleanupFunction(() => {
|
||||||
|
Services.prefs.clearUserPref("signon.autofillForms");
|
||||||
|
Services.logins.removeAllLogins();
|
||||||
|
});
|
||||||
|
for (let login of loginList()) {
|
||||||
|
Services.logins.addLogin(login);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the context menu is populated with the right
|
||||||
|
* menuitems for the target password input field.
|
||||||
|
*/
|
||||||
|
add_task(function* test_context_menu_populate() {
|
||||||
|
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");
|
||||||
|
|
||||||
|
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 password field is correctly filled when one
|
||||||
|
* 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",
|
||||||
|
}, function* (browser) {
|
||||||
|
for (let testCase of testSet) {
|
||||||
|
let passwordInput = browser.contentWindow.document.getElementById(testCase.passwordInput);
|
||||||
|
|
||||||
|
yield openPasswordContextMenu(browser, passwordInput);
|
||||||
|
|
||||||
|
let popupMenu = document.getElementById("fill-login-popup");
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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(passwordInput, "input", "Password input value changed");
|
||||||
|
|
||||||
|
// Find the used login by it's username (Use only unique usernames in this test).
|
||||||
|
let login = getLoginFromUsername(firstLoginItem.label);
|
||||||
|
|
||||||
|
Assert.equal(login.password, passwordInput.value, "Password filled and correct.");
|
||||||
|
|
||||||
|
// 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");
|
||||||
|
contextMenu.hidePopup();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the password field is correctly filled when it's in an iframe.
|
||||||
|
*/
|
||||||
|
add_task(function* test_context_menu_iframe_fill() {
|
||||||
|
yield BrowserTestUtils.withNewTab({
|
||||||
|
gBrowser,
|
||||||
|
url: TEST_HOSTNAME + "/browser/toolkit/components/" +
|
||||||
|
"passwordmgr/test/browser/multiple_forms.html",
|
||||||
|
}, function* (browser) {
|
||||||
|
let iframe = browser.contentWindow.document.getElementById("test-iframe");
|
||||||
|
let passwordInput = iframe.contentDocument.getElementById("form-basic-password");
|
||||||
|
|
||||||
|
let contextMenuShownPromise = BrowserTestUtils.waitForEvent(window, "popupshown");
|
||||||
|
let eventDetails = {type: "contextmenu", button: 2};
|
||||||
|
|
||||||
|
// To click at the right point we have to take into account the iframe offset.
|
||||||
|
let iframeRect = iframe.getBoundingClientRect();
|
||||||
|
let inputRect = passwordInput.getBoundingClientRect();
|
||||||
|
let clickPos = {
|
||||||
|
offsetX: iframeRect.left + inputRect.width / 2,
|
||||||
|
offsetY: iframeRect.top + inputRect.height / 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Synthesize a right mouse click over the password input element.
|
||||||
|
BrowserTestUtils.synthesizeMouse(passwordInput, clickPos.offsetX, clickPos.offsetY, eventDetails, browser);
|
||||||
|
yield contextMenuShownPromise;
|
||||||
|
|
||||||
|
// Synthesize a mouse click over the fill login menu header.
|
||||||
|
let popupHeader = document.getElementById("fill-login");
|
||||||
|
let popupShownPromise = BrowserTestUtils.waitForEvent(popupHeader, "popupshown");
|
||||||
|
EventUtils.synthesizeMouseAtCenter(popupHeader, {});
|
||||||
|
yield popupShownPromise;
|
||||||
|
|
||||||
|
let popupMenu = document.getElementById("fill-login-popup");
|
||||||
|
|
||||||
|
// Stores the original value of username
|
||||||
|
let usernameInput = iframe.contentDocument.getElementById("form-basic-username");
|
||||||
|
let usernameOriginalValue = usernameInput.value;
|
||||||
|
|
||||||
|
// Execute the command of the first login menuitem found at the context menu.
|
||||||
|
let firstLoginItem = popupMenu.getElementsByClassName("context-login-item")[0];
|
||||||
|
firstLoginItem.doCommand();
|
||||||
|
|
||||||
|
yield BrowserTestUtils.waitForEvent(passwordInput, "input", "Password input value changed");
|
||||||
|
|
||||||
|
// Find the used login by it's username.
|
||||||
|
let login = getLoginFromUsername(firstLoginItem.label);
|
||||||
|
|
||||||
|
Assert.equal(login.password, passwordInput.value, "Password filled and correct.");
|
||||||
|
|
||||||
|
Assert.equal(usernameOriginalValue,
|
||||||
|
usernameInput.value,
|
||||||
|
"Username value was not changed.");
|
||||||
|
|
||||||
|
let contextMenu = document.getElementById("contentAreaContextMenu");
|
||||||
|
contextMenu.hidePopup();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synthesize mouse clicks to open the password manager context menu popup
|
||||||
|
* for a target password input element.
|
||||||
|
*/
|
||||||
|
function* openPasswordContextMenu(browser, passwordInput) {
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// Synthesize a mouse click over the fill login menu header.
|
||||||
|
let popupHeader = document.getElementById("fill-login");
|
||||||
|
let popupShownPromise = BrowserTestUtils.waitForEvent(popupHeader, "popupshown");
|
||||||
|
EventUtils.synthesizeMouseAtCenter(popupHeader, {});
|
||||||
|
yield popupShownPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if every login that matches the page hostname are available at the context menu.
|
||||||
|
*/
|
||||||
|
function checkMenu(contextMenu) {
|
||||||
|
let logins = loginList().filter(login => login.hostname == TEST_HOSTNAME);
|
||||||
|
// Make an array of menuitems for easier comparison.
|
||||||
|
let menuitems = [...contextMenu.getElementsByClassName("context-login-item")];
|
||||||
|
Assert.equal(menuitems.length, logins.length, "Same amount of menu items and expected logins.");
|
||||||
|
Assert.ok(logins.every(l => menuitems.some(m => l.username == m.label)), "Every login have an item at the menu.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for a login by it's username.
|
||||||
|
*
|
||||||
|
* Only unique login/hostname combinations should be used at this test.
|
||||||
|
*/
|
||||||
|
function getLoginFromUsername(username) {
|
||||||
|
return loginList().find(login => login.username == username);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of logins used for the test.
|
||||||
|
*
|
||||||
|
* We should only use unique usernames in this test,
|
||||||
|
* because we need to search logins by username.
|
||||||
|
*/
|
||||||
|
function loginList() {
|
||||||
|
return [
|
||||||
|
LoginTestUtils.testData.formLogin({
|
||||||
|
hostname: "https://example.com",
|
||||||
|
formSubmitURL: "https://example.com",
|
||||||
|
username: "username",
|
||||||
|
password: "password",
|
||||||
|
}),
|
||||||
|
LoginTestUtils.testData.formLogin({
|
||||||
|
hostname: "http://example.com",
|
||||||
|
formSubmitURL: "http://example.com",
|
||||||
|
username: "username1",
|
||||||
|
password: "password1",
|
||||||
|
}),
|
||||||
|
LoginTestUtils.testData.formLogin({
|
||||||
|
hostname: "https://example.com",
|
||||||
|
formSubmitURL: "https://example.com",
|
||||||
|
username: "username2",
|
||||||
|
password: "password2",
|
||||||
|
}),
|
||||||
|
LoginTestUtils.testData.formLogin({
|
||||||
|
hostname: "https://example.org",
|
||||||
|
formSubmitURL: "https://example.org",
|
||||||
|
username: "username-cross-origin",
|
||||||
|
password: "password-cross-origin",
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
<!DOCTYPE html><html><head><meta charset="utf-8"></head><body>
|
||||||
|
<!-- Any copyright is dedicated to the Public Domain.
|
||||||
|
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||||
|
|
||||||
|
<!-- Password only form -->
|
||||||
|
<form id='form-1'>
|
||||||
|
<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'>
|
||||||
|
<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'>
|
||||||
|
<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'>
|
||||||
|
<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'>
|
||||||
|
<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'>
|
||||||
|
<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'>
|
||||||
|
<input id='test-password-7' type='password' name='pname' value="testpass">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Form in an iframe -->
|
||||||
|
<iframe src="https://example.org/browser/toolkit/components/passwordmgr/test/browser/form_basic.html" id="test-iframe"></iframe>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -129,11 +129,11 @@ const MockDocument = {
|
|||||||
/**
|
/**
|
||||||
* Create a document for the given URL containing the given HTML with the ownerDocument of all <form>s having a mocked location.
|
* Create a document for the given URL containing the given HTML with the ownerDocument of all <form>s having a mocked location.
|
||||||
*/
|
*/
|
||||||
createTestDocument(aDocumentURL, aHTML = "<form>") {
|
createTestDocument(aDocumentURL, aContent = "<form>", aType = "text/html") {
|
||||||
let parser = Cc["@mozilla.org/xmlextras/domparser;1"].
|
let parser = Cc["@mozilla.org/xmlextras/domparser;1"].
|
||||||
createInstance(Ci.nsIDOMParser);
|
createInstance(Ci.nsIDOMParser);
|
||||||
parser.init();
|
parser.init();
|
||||||
let parsedDoc = parser.parseFromString(aHTML, "text/html");
|
let parsedDoc = parser.parseFromString(aContent, aType);
|
||||||
|
|
||||||
for (let element of parsedDoc.forms) {
|
for (let element of parsedDoc.forms) {
|
||||||
this.mockOwnerDocumentProperty(element, parsedDoc, aDocumentURL);
|
this.mockOwnerDocumentProperty(element, parsedDoc, aDocumentURL);
|
||||||
|
165
toolkit/components/passwordmgr/test/unit/test_context_menu.js
Normal file
165
toolkit/components/passwordmgr/test/unit/test_context_menu.js
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
* Test the password manager context menu.
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
Cu.import("resource://gre/modules/LoginManagerContextMenu.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyGetter(this, "_stringBundle", function() {
|
||||||
|
return Services.strings.
|
||||||
|
createBundle("chrome://passwordmgr/locale/passwordmgr.properties");
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare data for the following tests.
|
||||||
|
*/
|
||||||
|
add_task(function* test_initialize() {
|
||||||
|
for (let login of loginList()) {
|
||||||
|
Services.logins.addLogin(login);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if the LoginManagerContextMenu returns the correct login items.
|
||||||
|
*/
|
||||||
|
add_task(function* test_contextMenuAddAndRemoveLogins() {
|
||||||
|
const DOCUMENT_CONTENT = "<form><input id='pw' type=password></form>";
|
||||||
|
const INPUT_QUERY = "input[type='password']";
|
||||||
|
|
||||||
|
let testHostnames = [
|
||||||
|
"http://www.example.com",
|
||||||
|
"http://www2.example.com",
|
||||||
|
"http://www3.example.com",
|
||||||
|
"http://empty.example.com",
|
||||||
|
];
|
||||||
|
|
||||||
|
for (let hostname of testHostnames) {
|
||||||
|
do_print("test for hostname: " + hostname);
|
||||||
|
// Get expected logins for this test.
|
||||||
|
let logins = getExpectedLogins(hostname);
|
||||||
|
|
||||||
|
// Create the logins menuitems fragment.
|
||||||
|
let {fragment, document} = createLoginsFragment(hostname, DOCUMENT_CONTENT, INPUT_QUERY);
|
||||||
|
|
||||||
|
if (!logins.length) {
|
||||||
|
Assert.ok(fragment === null, "Null returned. No logins where found.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let items = [...fragment.querySelectorAll("menuitem")];
|
||||||
|
|
||||||
|
// Check if the items are those expected to be listed.
|
||||||
|
Assert.ok(checkLoginItems(logins, items), "All expected logins found.");
|
||||||
|
document.body.appendChild(fragment);
|
||||||
|
|
||||||
|
// Try to clear the fragment.
|
||||||
|
LoginManagerContextMenu.clearLoginsFromMenu(document);
|
||||||
|
Assert.equal(fragment.querySelectorAll("menuitem").length, 0, "All items correctly cleared.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Services.logins.removeAllLogins();
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a fragment with a menuitem for each login.
|
||||||
|
*/
|
||||||
|
function createLoginsFragment(url, content, elementQuery) {
|
||||||
|
const CHROME_URL = "chrome://mock-chrome";
|
||||||
|
|
||||||
|
// Create a mock document.
|
||||||
|
let document = MockDocument.createTestDocument(CHROME_URL, content);
|
||||||
|
let inputElement = document.querySelector(elementQuery);
|
||||||
|
MockDocument.mockOwnerDocumentProperty(inputElement, document, url);
|
||||||
|
|
||||||
|
// We also need a simple mock Browser object for this test.
|
||||||
|
let browser = {
|
||||||
|
ownerDocument: document
|
||||||
|
};
|
||||||
|
|
||||||
|
let URI = Services.io.newURI(url, null, null);
|
||||||
|
return {
|
||||||
|
document,
|
||||||
|
fragment: LoginManagerContextMenu.addLoginsToMenu(inputElement, browser, URI),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if every login have it's corresponding menuitem.
|
||||||
|
* Duplicates and empty usernames have a date appended.
|
||||||
|
*/
|
||||||
|
function checkLoginItems(logins, items) {
|
||||||
|
function findDuplicates(loginList) {
|
||||||
|
var seen = new Set();
|
||||||
|
var duplicates = new Set();
|
||||||
|
for (let login of loginList) {
|
||||||
|
if (seen.has(login.username)) {
|
||||||
|
duplicates.add(login.username);
|
||||||
|
}
|
||||||
|
seen.add(login.username);
|
||||||
|
}
|
||||||
|
return duplicates;
|
||||||
|
}
|
||||||
|
let duplicates = findDuplicates(logins);
|
||||||
|
|
||||||
|
let dateAndTimeFormatter = new Intl.DateTimeFormat(undefined,
|
||||||
|
{ day: "numeric", month: "short", year: "numeric" });
|
||||||
|
for (let login of logins) {
|
||||||
|
if (login.username && !duplicates.has(login.username)) {
|
||||||
|
// If login is not duplicate and we can't find an item for it, fail.
|
||||||
|
if (!items.find(item => item.label == login.username)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let meta = login.QueryInterface(Ci.nsILoginMetaInfo);
|
||||||
|
let time = dateAndTimeFormatter.format(new Date(meta.timePasswordChanged));
|
||||||
|
// If login is duplicate, check if we have a login item with appended date.
|
||||||
|
if (login.username && !items.find(item => item.label == login.username + " (" + time + ")")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// If login is empty, check if we have a login item with appended date.
|
||||||
|
if (!login.username &&
|
||||||
|
!items.find(item => item.label == _stringBundle.GetStringFromName("noUsername") + " (" + time + ")")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the list of expected logins for a hostname.
|
||||||
|
*/
|
||||||
|
function getExpectedLogins(hostname) {
|
||||||
|
return Services.logins.getAllLogins().filter(entry => entry["hostname"] === hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
function loginList() {
|
||||||
|
return [
|
||||||
|
new LoginInfo("http://www.example.com", "http://www.example.com", null,
|
||||||
|
"username1", "password",
|
||||||
|
"form_field_username", "form_field_password"),
|
||||||
|
|
||||||
|
new LoginInfo("http://www.example.com", "http://www.example.com", null,
|
||||||
|
"username2", "password",
|
||||||
|
"form_field_username", "form_field_password"),
|
||||||
|
|
||||||
|
new LoginInfo("http://www2.example.com", "http://www.example.com", null,
|
||||||
|
"username", "password",
|
||||||
|
"form_field_username", "form_field_password"),
|
||||||
|
new LoginInfo("http://www2.example.com", "http://www2.example.com", null,
|
||||||
|
"username", "password2",
|
||||||
|
"form_field_username", "form_field_password"),
|
||||||
|
new LoginInfo("http://www2.example.com", "http://www2.example.com", null,
|
||||||
|
"username2", "password2",
|
||||||
|
"form_field_username", "form_field_password"),
|
||||||
|
|
||||||
|
new LoginInfo("http://www3.example.com", "http://www.example.com", null,
|
||||||
|
"", "password",
|
||||||
|
"form_field_username", "form_field_password"),
|
||||||
|
new LoginInfo("http://www3.example.com", "http://www3.example.com", null,
|
||||||
|
"", "password2",
|
||||||
|
"form_field_username", "form_field_password"),
|
||||||
|
];
|
||||||
|
}
|
@ -15,6 +15,7 @@ skip-if = os == "android"
|
|||||||
skip-if = true || os != "android" # Bug 1171687: Needs fixing on Android
|
skip-if = true || os != "android" # Bug 1171687: Needs fixing on Android
|
||||||
|
|
||||||
# The following tests apply to any storage back-end.
|
# The following tests apply to any storage back-end.
|
||||||
|
[test_context_menu.js]
|
||||||
[test_disabled_hosts.js]
|
[test_disabled_hosts.js]
|
||||||
[test_getFormFields.js]
|
[test_getFormFields.js]
|
||||||
[test_getPasswordFields.js]
|
[test_getPasswordFields.js]
|
||||||
|
Loading…
Reference in New Issue
Block a user