зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1550095 - Add Save Changes and Cancel button for LoginItem. r=MattN,Pike
Differential Revision: https://phabricator.services.mozilla.com/D30540 --HG-- rename : browser/components/aboutlogins/tests/browser/browser_loginChanges.js => browser/components/aboutlogins/tests/browser/browser_loginListChanges.js extra : moz-landing-system : lando
This commit is contained in:
Родитель
50a50caf58
Коммит
03f122082c
|
@ -36,6 +36,7 @@ let LEGACY_ACTORS = {
|
|||
module: "resource:///actors/AboutLoginsChild.jsm",
|
||||
events: {
|
||||
"AboutLoginsDeleteLogin": {wantUntrusted: true},
|
||||
"AboutLoginsUpdateLogin": {wantUntrusted: true},
|
||||
"AboutLoginsInit": {wantUntrusted: true},
|
||||
},
|
||||
messages: [
|
||||
|
@ -545,6 +546,7 @@ const listeners = {
|
|||
|
||||
mm: {
|
||||
"AboutLogins:DeleteLogin": ["AboutLoginsParent"],
|
||||
"AboutLogins:UpdateLogin": ["AboutLoginsParent"],
|
||||
"AboutLogins:Subscribe": ["AboutLoginsParent"],
|
||||
"Content:Click": ["ContentClick"],
|
||||
"ContentSearch": ["ContentSearch"],
|
||||
|
|
|
@ -30,6 +30,10 @@ class AboutLoginsChild extends ActorChild {
|
|||
this.mm.sendAsyncMessage("AboutLogins:DeleteLogin", {login: event.detail});
|
||||
break;
|
||||
}
|
||||
case "AboutLoginsUpdateLogin": {
|
||||
this.mm.sendAsyncMessage("AboutLogins:UpdateLogin", {login: event.detail});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,11 +6,16 @@
|
|||
|
||||
var EXPORTED_SYMBOLS = ["AboutLoginsParent"];
|
||||
|
||||
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "LoginHelper",
|
||||
"resource://gre/modules/LoginHelper.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "Services",
|
||||
"resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
return LoginHelper.createLogger("AboutLoginsParent");
|
||||
});
|
||||
|
||||
const ABOUT_LOGINS_ORIGIN = "about:logins";
|
||||
|
||||
const isValidLogin = login => {
|
||||
|
@ -52,6 +57,25 @@ var AboutLoginsParent = {
|
|||
messageManager.sendAsyncMessage("AboutLogins:AllLogins", this.getAllLogins());
|
||||
break;
|
||||
}
|
||||
case "AboutLogins:UpdateLogin": {
|
||||
let loginUpdates = message.data.login;
|
||||
let logins = LoginHelper.searchLoginsWithObject({guid: loginUpdates.guid});
|
||||
if (!logins || logins.length != 1) {
|
||||
log.warn(`AboutLogins:UpdateLogin: expected to find a login for guid: ${loginUpdates.guid} but found ${(logins || []).length}`);
|
||||
return;
|
||||
}
|
||||
|
||||
let modifiedLogin = logins[0].clone();
|
||||
if (loginUpdates.hasOwnProperty("username")) {
|
||||
modifiedLogin.username = loginUpdates.username;
|
||||
}
|
||||
if (loginUpdates.hasOwnProperty("password")) {
|
||||
modifiedLogin.password = loginUpdates.password;
|
||||
}
|
||||
|
||||
Services.logins.modifyLogin(logins[0], modifiedLogin);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -95,7 +119,8 @@ var AboutLoginsParent = {
|
|||
messageSubscribers(name, details) {
|
||||
let subscribers = ChromeUtils.nondeterministicGetWeakSetKeys(this._subscribers);
|
||||
for (let subscriber of subscribers) {
|
||||
if (subscriber.contentPrincipal.originNoSuffix != ABOUT_LOGINS_ORIGIN) {
|
||||
if (!subscriber.contentPrincipal ||
|
||||
subscriber.contentPrincipal.originNoSuffix != ABOUT_LOGINS_ORIGIN) {
|
||||
this._subscribers.delete(subscriber);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -16,8 +16,12 @@ login-list =
|
|||
.login-list-header = Logins
|
||||
|
||||
login-item =
|
||||
.cancel-button = Cancel
|
||||
.delete-button = Delete
|
||||
.hostname-label = Hostname
|
||||
.hostname-label = Website Address
|
||||
.password-label = Password
|
||||
.time-created-label = Time Created
|
||||
.save-changes-button = Save Changes
|
||||
.time-created = Created: { DATETIME($timeCreated, day: "numeric", month: "long", year: "numeric") }
|
||||
.time-changed = Last changed: { DATETIME($timeChanged, day: "numeric", month: "long", year: "numeric") }
|
||||
.time-used = Last used: { DATETIME($timeUsed, day: "numeric", month: "long", year: "numeric") }
|
||||
.username-label = Username
|
||||
|
|
|
@ -18,10 +18,14 @@
|
|||
<login-list data-l10n-id="login-list"
|
||||
data-l10n-attrs="login-list-header"></login-list>
|
||||
<login-item data-l10n-id="login-item"
|
||||
data-l10n-attrs="delete-button,
|
||||
data-l10n-attrs="cancel-button,
|
||||
delete-button,
|
||||
hostname-label,
|
||||
password-label,
|
||||
time-created-label,
|
||||
save-changes-button,
|
||||
time-created,
|
||||
time-changed,
|
||||
time-used,
|
||||
username-label"></login-item>
|
||||
|
||||
<template id="login-list-template">
|
||||
|
@ -43,23 +47,24 @@
|
|||
<template id="login-item-template">
|
||||
<link rel="stylesheet" href="chrome://browser/content/aboutlogins/components/login-item.css">
|
||||
<h2 class="header"></h2>
|
||||
<button class="delete-button"></button>
|
||||
<label>
|
||||
<span class="hostname-label"></span>
|
||||
<input name="hostname"/>
|
||||
<span class="hostname-label field-label"></span>
|
||||
<span class="hostname"/>
|
||||
</label>
|
||||
<label>
|
||||
<span class="username-label"></span>
|
||||
<span class="username-label field-label"></span>
|
||||
<input name="username"/>
|
||||
</label>
|
||||
<label>
|
||||
<span class="password-label"></span>
|
||||
<span class="password-label field-label"></span>
|
||||
<input type="password" name="password"/>
|
||||
</label>
|
||||
<p>
|
||||
<span class="time-created-label"></span>
|
||||
<span class="time-created"></span>
|
||||
</p>
|
||||
<button class="delete-button"></button>
|
||||
<p class="time-created meta-info"></p>
|
||||
<p class="time-changed meta-info"></p>
|
||||
<p class="time-used meta-info"></p>
|
||||
<button class="save-changes-button"></button>
|
||||
<button class="cancel-button"></button>
|
||||
</template>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -19,7 +19,6 @@ window.addEventListener("AboutLoginsChromeToContent", event => {
|
|||
}
|
||||
case "LoginAdded": {
|
||||
gElements.loginList.loginAdded(event.detail.value);
|
||||
gElements.loginItem.loginAdded(event.detail.value);
|
||||
break;
|
||||
}
|
||||
case "LoginModified": {
|
||||
|
|
|
@ -9,3 +9,23 @@
|
|||
h2 {
|
||||
border-bottom: 1px solid var(--grey-30);
|
||||
}
|
||||
|
||||
.field-label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.meta-info {
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.meta-info:not(:first-of-type) {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.meta-info:not(:last-of-type) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.meta-info:first-of-type {
|
||||
border-top: 1px solid var(--grey-30);
|
||||
}
|
||||
|
|
|
@ -18,8 +18,14 @@ class LoginItem extends HTMLElement {
|
|||
this.attachShadow({mode: "open"})
|
||||
.appendChild(loginItemTemplate.content.cloneNode(true));
|
||||
|
||||
let deleteButton = this.shadowRoot.querySelector(".delete-button");
|
||||
deleteButton.addEventListener("click", this);
|
||||
for (let selector of [
|
||||
".delete-button",
|
||||
".save-changes-button",
|
||||
".cancel-button",
|
||||
]) {
|
||||
let button = this.shadowRoot.querySelector(selector);
|
||||
button.addEventListener("click", this);
|
||||
}
|
||||
|
||||
window.addEventListener("AboutLoginsLoginSelected", this);
|
||||
|
||||
|
@ -28,10 +34,14 @@ class LoginItem extends HTMLElement {
|
|||
|
||||
static get observedAttributes() {
|
||||
return [
|
||||
"cancel-button",
|
||||
"delete-button",
|
||||
"hostname-label",
|
||||
"password-label",
|
||||
"time-created-label",
|
||||
"save-changes-button",
|
||||
"time-created",
|
||||
"time-changed",
|
||||
"time-used",
|
||||
"username-label",
|
||||
];
|
||||
}
|
||||
|
@ -50,10 +60,17 @@ class LoginItem extends HTMLElement {
|
|||
}
|
||||
|
||||
render() {
|
||||
this.shadowRoot.querySelector("input[name='hostname']").value = this._login.hostname || "";
|
||||
let l10nArgs = {
|
||||
timeCreated: this._login.timeCreated || "",
|
||||
timeChanged: this._login.timePasswordChanged || "",
|
||||
timeUsed: this._login.timeLastUsed || "",
|
||||
};
|
||||
document.l10n.setAttributes(this, "login-item", l10nArgs);
|
||||
let hostnameNoScheme = this._login.hostname && new URL(this._login.hostname).hostname;
|
||||
this.shadowRoot.querySelector(".header").textContent = hostnameNoScheme || "";
|
||||
this.shadowRoot.querySelector(".hostname").textContent = this._login.hostname || "";
|
||||
this.shadowRoot.querySelector("input[name='username']").value = this._login.username || "";
|
||||
this.shadowRoot.querySelector("input[name='password']").value = this._login.password || "";
|
||||
this.shadowRoot.querySelector(".time-created").textContent = this._login.timeCreated || "";
|
||||
}
|
||||
|
||||
handleEvent(event) {
|
||||
|
@ -68,6 +85,28 @@ class LoginItem extends HTMLElement {
|
|||
bubbles: true,
|
||||
detail: this._login,
|
||||
}));
|
||||
return;
|
||||
}
|
||||
if (event.target.classList.contains("save-changes-button")) {
|
||||
let loginUpdates = {
|
||||
guid: this._login.guid,
|
||||
};
|
||||
let formUsername = this.shadowRoot.querySelector("input[name='username']").value.trim();
|
||||
if (formUsername != this._login.username) {
|
||||
loginUpdates.username = formUsername;
|
||||
}
|
||||
let formPassword = this.shadowRoot.querySelector("input[name='password']").value.trim();
|
||||
if (formPassword != this._login.password) {
|
||||
loginUpdates.password = formPassword;
|
||||
}
|
||||
document.dispatchEvent(new CustomEvent("AboutLoginsUpdateLogin", {
|
||||
bubbles: true,
|
||||
detail: loginUpdates,
|
||||
}));
|
||||
return;
|
||||
}
|
||||
if (event.target.classList.contains("cancel-button")) {
|
||||
this.render();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -79,27 +118,6 @@ class LoginItem extends HTMLElement {
|
|||
this.render();
|
||||
}
|
||||
|
||||
loginAdded(login) {
|
||||
if (!this._login.guid) {
|
||||
let tempLogin = {
|
||||
username: this.shadowRoot.querySelector("input[name='username']").value,
|
||||
formSubmitURL: "", // Use the wildcard since the user doesn't supply it.
|
||||
hostname: this.shadowRoot.querySelector("input[name='hostname']").value,
|
||||
password: this.shadowRoot.querySelector("input[name='password']").value,
|
||||
};
|
||||
// Need to use LoginHelper.doLoginsMatch() to see if the login
|
||||
// that was added is the login that was being edited, so we
|
||||
// can update time-created, etc.
|
||||
if (window.AboutLoginsUtils.doLoginsMatch(tempLogin, login)) {
|
||||
this._login = login;
|
||||
this.render();
|
||||
}
|
||||
} else if (login.guid == this._login.guid) {
|
||||
this._login = login;
|
||||
this.render();
|
||||
}
|
||||
}
|
||||
|
||||
loginModified(login) {
|
||||
if (login.guid != this._login.guid) {
|
||||
return;
|
||||
|
|
|
@ -3,4 +3,5 @@ prefs =
|
|||
signon.management.page.enabled=true
|
||||
|
||||
[browser_deleteLogin.js]
|
||||
[browser_loginChanges.js]
|
||||
[browser_loginListChanges.js]
|
||||
[browser_updateLogin.js]
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let nsLoginInfo = new Components.Constructor("@mozilla.org/login-manager/loginInfo;1",
|
||||
Ci.nsILoginInfo, "init");
|
||||
const LOGIN_URL = "https://www.example.com";
|
||||
let TEST_LOGIN1 = new nsLoginInfo(LOGIN_URL, LOGIN_URL, null, "user1", "pass1", "username", "password");
|
||||
|
||||
add_task(async function setup() {
|
||||
TEST_LOGIN1 = Services.logins.addLogin(TEST_LOGIN1);
|
||||
await BrowserTestUtils.openNewForegroundTab({gBrowser, url: "about:logins"});
|
||||
registerCleanupFunction(() => {
|
||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_show_logins() {
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
await ContentTask.spawn(browser, TEST_LOGIN1.guid, async (loginGuid) => {
|
||||
let loginList = Cu.waiveXrays(content.document.querySelector("login-list"));
|
||||
let loginFound = await ContentTaskUtils.waitForCondition(() => {
|
||||
return loginList._logins.length == 1 &&
|
||||
loginList._logins[0].guid == loginGuid;
|
||||
}, "Waiting for login to be displayed");
|
||||
ok(loginFound, "Stored logins should be displayed upon loading the page");
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_login_item() {
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
await ContentTask.spawn(browser, LoginHelper.loginToVanillaObject(TEST_LOGIN1), async (login) => {
|
||||
let loginList = content.document.querySelector("login-list");
|
||||
let loginListItem = Cu.waiveXrays(loginList.shadowRoot.querySelector("login-list-item"));
|
||||
loginListItem.click();
|
||||
|
||||
let loginItem = Cu.waiveXrays(content.document.querySelector("login-item"));
|
||||
let loginItemPopulated = await ContentTaskUtils.waitForCondition(() => {
|
||||
return loginItem._login.guid == loginListItem.getAttribute("guid") &&
|
||||
loginItem._login.guid == login.guid;
|
||||
}, "Waiting for login item to get populated");
|
||||
ok(loginItemPopulated, "The login item should get populated");
|
||||
|
||||
let usernameInput = loginItem.shadowRoot.querySelector("input[name='username']");
|
||||
let passwordInput = loginItem.shadowRoot.querySelector("input[name='password']");
|
||||
|
||||
usernameInput.value += "-undome";
|
||||
passwordInput.value += "-undome";
|
||||
|
||||
let cancelButton = loginItem.shadowRoot.querySelector(".cancel-button");
|
||||
cancelButton.click();
|
||||
await Promise.resolve();
|
||||
is(usernameInput.value, login.username, "Username change should be reverted");
|
||||
is(passwordInput.value, login.password, "Password change should be reverted");
|
||||
|
||||
usernameInput.value += "-saveme";
|
||||
passwordInput.value += "-saveme";
|
||||
|
||||
let saveChangesButton = loginItem.shadowRoot.querySelector(".save-changes-button");
|
||||
saveChangesButton.click();
|
||||
|
||||
await ContentTaskUtils.waitForCondition(() => {
|
||||
return loginListItem._login.username == usernameInput.value &&
|
||||
loginListItem._login.password == passwordInput.value;
|
||||
}, "Waiting for corresponding login in login list to update");
|
||||
});
|
||||
});
|
|
@ -1,6 +1,6 @@
|
|||
"use strict";
|
||||
|
||||
/* exported asyncElementRendered, importDependencies */
|
||||
/* exported asyncElementRendered, importDependencies, stubFluentL10n */
|
||||
|
||||
/**
|
||||
* A helper to await on while waiting for an asynchronous rendering of a Custom
|
||||
|
@ -24,3 +24,15 @@ function importDependencies(templateFrame, destinationEl) {
|
|||
destinationEl.appendChild(imported);
|
||||
}
|
||||
}
|
||||
|
||||
function stubFluentL10n(argsMap) {
|
||||
document.l10n = {
|
||||
setAttributes(element, id, args) {
|
||||
element.setAttribute("data-l10n-id", id);
|
||||
for (let attrName of Object.keys(argsMap)) {
|
||||
let varName = argsMap[attrName];
|
||||
element.setAttribute(attrName, args[varName]);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -31,9 +31,17 @@ const TEST_LOGIN_1 = {
|
|||
username: "user1",
|
||||
password: "pass1",
|
||||
timeCreated: "1000",
|
||||
timePasswordChanged: "2000",
|
||||
timeLastUsed: "4000",
|
||||
};
|
||||
|
||||
add_task(async function setup() {
|
||||
stubFluentL10n({
|
||||
"time-created": "timeCreated",
|
||||
"time-changed": "timeChanged",
|
||||
"time-used": "timeUsed",
|
||||
});
|
||||
|
||||
let templateFrame = document.getElementById("templateFrame");
|
||||
let displayEl = document.getElementById("display");
|
||||
importDependencies(templateFrame, displayEl);
|
||||
|
@ -44,20 +52,24 @@ add_task(async function setup() {
|
|||
|
||||
add_task(async function test_empty_item() {
|
||||
ok(gLoginItem, "loginItem exists");
|
||||
is(gLoginItem.shadowRoot.querySelector("input[name='hostname']").value, "", "hostname should be blank");
|
||||
is(gLoginItem.shadowRoot.querySelector(".hostname").textContent, "", "hostname should be blank");
|
||||
is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, "", "username should be blank");
|
||||
is(gLoginItem.shadowRoot.querySelector("input[name='password']").value, "", "password should be blank");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, "", "time-created should be blank");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-changed").textContent, "", "time-changed should be blank");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-used").textContent, "", "time-used should be blank");
|
||||
});
|
||||
|
||||
add_task(async function test_set_login() {
|
||||
gLoginItem.setLogin(TEST_LOGIN_1);
|
||||
await asyncElementRendered();
|
||||
|
||||
is(gLoginItem.shadowRoot.querySelector("input[name='hostname']").value, TEST_LOGIN_1.hostname, "hostname should be populated");
|
||||
is(gLoginItem.shadowRoot.querySelector(".hostname").textContent, TEST_LOGIN_1.hostname, "hostname should be populated");
|
||||
is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, TEST_LOGIN_1.username, "username should be populated");
|
||||
is(gLoginItem.shadowRoot.querySelector("input[name='password']").value, TEST_LOGIN_1.password, "password should be populated");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, TEST_LOGIN_1.timeCreated, "time-created should be populated");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-changed").textContent, TEST_LOGIN_1.timePasswordChanged, "time-changed should be populated");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-used").textContent, TEST_LOGIN_1.timeLastUsed, "time-used should be populated");
|
||||
});
|
||||
|
||||
add_task(async function test_different_login_modified() {
|
||||
|
@ -65,10 +77,12 @@ add_task(async function test_different_login_modified() {
|
|||
gLoginItem.loginModified(otherLogin);
|
||||
await asyncElementRendered();
|
||||
|
||||
is(gLoginItem.shadowRoot.querySelector("input[name='hostname']").value, TEST_LOGIN_1.hostname, "hostname should be unchanged");
|
||||
is(gLoginItem.shadowRoot.querySelector(".hostname").textContent, TEST_LOGIN_1.hostname, "hostname should be unchanged");
|
||||
is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, TEST_LOGIN_1.username, "username should be unchanged");
|
||||
is(gLoginItem.shadowRoot.querySelector("input[name='password']").value, TEST_LOGIN_1.password, "password should be unchanged");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, TEST_LOGIN_1.timeCreated, "time-created should be unchanged");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-changed").textContent, TEST_LOGIN_1.timePasswordChanged, "time-changed should be unchanged");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-used").textContent, TEST_LOGIN_1.timeLastUsed, "time-used should be unchanged");
|
||||
});
|
||||
|
||||
add_task(async function test_different_login_removed() {
|
||||
|
@ -76,10 +90,12 @@ add_task(async function test_different_login_removed() {
|
|||
gLoginItem.loginRemoved(otherLogin);
|
||||
await asyncElementRendered();
|
||||
|
||||
is(gLoginItem.shadowRoot.querySelector("input[name='hostname']").value, TEST_LOGIN_1.hostname, "hostname should be unchanged");
|
||||
is(gLoginItem.shadowRoot.querySelector(".hostname").textContent, TEST_LOGIN_1.hostname, "hostname should be unchanged");
|
||||
is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, TEST_LOGIN_1.username, "username should be unchanged");
|
||||
is(gLoginItem.shadowRoot.querySelector("input[name='password']").value, TEST_LOGIN_1.password, "password should be unchanged");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, TEST_LOGIN_1.timeCreated, "time-created should be unchanged");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-changed").textContent, TEST_LOGIN_1.timePasswordChanged, "time-changed should be unchanged");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-used").textContent, TEST_LOGIN_1.timeLastUsed, "time-used should be unchanged");
|
||||
});
|
||||
|
||||
add_task(async function test_login_modified() {
|
||||
|
@ -87,20 +103,24 @@ add_task(async function test_login_modified() {
|
|||
gLoginItem.loginModified(modifiedLogin);
|
||||
await asyncElementRendered();
|
||||
|
||||
is(gLoginItem.shadowRoot.querySelector("input[name='hostname']").value, modifiedLogin.hostname, "hostname should be updated");
|
||||
is(gLoginItem.shadowRoot.querySelector(".hostname").textContent, modifiedLogin.hostname, "hostname should be updated");
|
||||
is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, modifiedLogin.username, "username should be updated");
|
||||
is(gLoginItem.shadowRoot.querySelector("input[name='password']").value, modifiedLogin.password, "password should be updated");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, modifiedLogin.timeCreated, "time-created should be updated");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-changed").textContent, modifiedLogin.timePasswordChanged, "time-changed should be updated");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-used").textContent, modifiedLogin.timeLastUsed, "time-used should be updated");
|
||||
});
|
||||
|
||||
add_task(async function test_login_removed() {
|
||||
gLoginItem.loginRemoved(TEST_LOGIN_1);
|
||||
await asyncElementRendered();
|
||||
|
||||
is(gLoginItem.shadowRoot.querySelector("input[name='hostname']").value, "", "hostname should be cleared");
|
||||
is(gLoginItem.shadowRoot.querySelector(".hostname").textContent, "", "hostname should be cleared");
|
||||
is(gLoginItem.shadowRoot.querySelector("input[name='username']").value, "", "username should be cleared");
|
||||
is(gLoginItem.shadowRoot.querySelector("input[name='password']").value, "", "password should be cleared");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-created").textContent, "", "time-created should be cleared");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-changed").textContent, "", "time-changed should be cleared");
|
||||
is(gLoginItem.shadowRoot.querySelector(".time-used").textContent, "", "time-used should be cleared");
|
||||
});
|
||||
|
||||
</script>
|
||||
|
|
Загрузка…
Ссылка в новой задаче