Bug 1776129 - Add Custom1-4 fields to Address Book UI. r=aleca
This converts nsIAbCard style Custom[1-4] properties to X-Custom[1-4] vCard properties when a card is edited. Since the properties could exist in either form a number of hacks have been deployed. Differential Revision: https://phabricator.services.mozilla.com/D153550 --HG-- extra : rebase_source : a793101ae36434240acca28e3892fe083520b170
This commit is contained in:
Родитель
f7a2b7878b
Коммит
2c2be3af27
|
@ -67,6 +67,11 @@ XPCOMUtils.defineLazyGetter(this, "SubDialog", function() {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
XPCOMUtils.defineLazyGetter(this, "bundle", function() {
|
||||||
|
return Services.strings.createBundle(
|
||||||
|
"chrome://messenger/locale/addressbook/addressBook.properties"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
UIDensity.registerWindow(window);
|
UIDensity.registerWindow(window);
|
||||||
UIFontSize.registerWindow(window);
|
UIFontSize.registerWindow(window);
|
||||||
|
@ -2398,10 +2403,7 @@ var detailsPane = {
|
||||||
|
|
||||||
let photoButton = document.getElementById("photoButton");
|
let photoButton = document.getElementById("photoButton");
|
||||||
// FIXME: Remove this once we get new strings after 102.
|
// FIXME: Remove this once we get new strings after 102.
|
||||||
let stringBundle = Services.strings.createBundle(
|
photoButton.title = bundle.GetStringFromName("browsePhoto");
|
||||||
"chrome://messenger/locale/addressbook/addressBook.properties"
|
|
||||||
);
|
|
||||||
photoButton.title = stringBundle.GetStringFromName("browsePhoto");
|
|
||||||
photoButton.addEventListener("click", () => {
|
photoButton.addEventListener("click", () => {
|
||||||
if (this._photoDetails.sourceURL) {
|
if (this._photoDetails.sourceURL) {
|
||||||
photoDialog.showWithURL(
|
photoDialog.showWithURL(
|
||||||
|
@ -2954,6 +2956,28 @@ var detailsPane = {
|
||||||
time.setAttribute("tz", tz);
|
time.setAttribute("tz", tz);
|
||||||
li.querySelector(".entry-value").appendChild(time);
|
li.querySelector(".entry-value").appendChild(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (let key of ["Custom1", "Custom2", "Custom3", "Custom4"]) {
|
||||||
|
// Custom properties can be nsIAbCard properties or vCard properties.
|
||||||
|
// If there's both, the vCard property has precedence.
|
||||||
|
let value = card.getProperty(key, "");
|
||||||
|
if (card.supportsVCard) {
|
||||||
|
value =
|
||||||
|
card.vCardProperties.getFirstValue(`x-${key.toLowerCase()}`) ?? value;
|
||||||
|
}
|
||||||
|
if (value) {
|
||||||
|
let li = list.appendChild(createEntryItem());
|
||||||
|
li.querySelector(".entry-type").textContent = bundle.GetStringFromName(
|
||||||
|
`property${key}`
|
||||||
|
);
|
||||||
|
li.querySelector(".entry-type").style.setProperty(
|
||||||
|
"white-space",
|
||||||
|
"nowrap"
|
||||||
|
);
|
||||||
|
li.querySelector(".entry-value").textContent = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
section.hidden = list.childElementCount == 0;
|
section.hidden = list.childElementCount == 0;
|
||||||
|
|
||||||
this.isEditing = false;
|
this.isEditing = false;
|
||||||
|
@ -3012,6 +3036,20 @@ var detailsPane = {
|
||||||
let card = this.currentCard;
|
let card = this.currentCard;
|
||||||
|
|
||||||
if (card && card.supportsVCard) {
|
if (card && card.supportsVCard) {
|
||||||
|
for (let key of ["Custom1", "Custom2", "Custom3", "Custom4"]) {
|
||||||
|
// Custom properties could still exist as nsIAbCard properties.
|
||||||
|
// If they do, and no vCard equivalent exists, add them to the vCard
|
||||||
|
// so that they get displayed.
|
||||||
|
let value = card.getProperty(key, "");
|
||||||
|
if (
|
||||||
|
value &&
|
||||||
|
card.vCardProperties.getFirstEntry(`x-${key.toLowerCase()}`) === null
|
||||||
|
) {
|
||||||
|
card.vCardProperties.addEntry(
|
||||||
|
new VCardPropertyEntry(`x-${key.toLowerCase()}`, {}, "text", value)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
this.vCardEdit.vCardProperties = card.vCardProperties;
|
this.vCardEdit.vCardProperties = card.vCardProperties;
|
||||||
// getProperty may return a "1" or "0" string, we want a boolean.
|
// getProperty may return a "1" or "0" string, we want a boolean.
|
||||||
this.vCardEdit.preferDisplayName.checked =
|
this.vCardEdit.preferDisplayName.checked =
|
||||||
|
@ -3059,13 +3097,10 @@ var detailsPane = {
|
||||||
*/
|
*/
|
||||||
handleInvalidForm() {
|
handleInvalidForm() {
|
||||||
// FIXME: Drop this in favor of an inline notification with fluent strings.
|
// FIXME: Drop this in favor of an inline notification with fluent strings.
|
||||||
let stringBundle = Services.strings.createBundle(
|
|
||||||
"chrome://messenger/locale/addressbook/addressBook.properties"
|
|
||||||
);
|
|
||||||
Services.prompt.alert(
|
Services.prompt.alert(
|
||||||
window,
|
window,
|
||||||
stringBundle.GetStringFromName("cardRequiredDataMissingTitle"),
|
bundle.GetStringFromName("cardRequiredDataMissingTitle"),
|
||||||
stringBundle.GetStringFromName("cardRequiredDataMissingMessage")
|
bundle.GetStringFromName("cardRequiredDataMissingMessage")
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -3126,6 +3161,12 @@ var detailsPane = {
|
||||||
this.vCardEdit.preferDisplayName.checked
|
this.vCardEdit.preferDisplayName.checked
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// By now, nsIAbCard custom properties should be on the vCard. Delete them.
|
||||||
|
card.deleteProperty("Custom1");
|
||||||
|
card.deleteProperty("Custom2");
|
||||||
|
card.deleteProperty("Custom3");
|
||||||
|
card.deleteProperty("Custom4");
|
||||||
|
|
||||||
// No photo or a new photo. Delete the old one.
|
// No photo or a new photo. Delete the old one.
|
||||||
if (this._photoChanged) {
|
if (this._photoChanged) {
|
||||||
let oldLeafName = card.getProperty("PhotoName", "");
|
let oldLeafName = card.getProperty("PhotoName", "");
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, you can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
/* globals VCardPropertyEntryView, vCardIdGen */
|
||||||
|
|
||||||
|
ChromeUtils.defineModuleGetter(
|
||||||
|
this,
|
||||||
|
"VCardPropertyEntry",
|
||||||
|
"resource:///modules/VCardUtils.jsm"
|
||||||
|
);
|
||||||
|
|
||||||
|
class VCardCustomComponent extends HTMLElement {
|
||||||
|
/** @type {VCardPropertyEntry[]} */
|
||||||
|
vCardPropertyEntries = null;
|
||||||
|
/** @type {HTMLInputElement[]} */
|
||||||
|
inputEls = null;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
let template = document.getElementById("template-vcard-edit-custom");
|
||||||
|
let clonedTemplate = template.content.cloneNode(true);
|
||||||
|
this.appendChild(clonedTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
if (this.isConnected) {
|
||||||
|
// FIXME: Add some Fluent strings so that we don't have to do this.
|
||||||
|
let stringBundle = Services.strings.createBundle(
|
||||||
|
"chrome://messenger/locale/addressbook/addressBook.properties"
|
||||||
|
);
|
||||||
|
|
||||||
|
this.inputEls = this.querySelectorAll("input");
|
||||||
|
let labelEls = this.querySelectorAll("label");
|
||||||
|
for (let i = 0; i < 4; i++) {
|
||||||
|
let inputId = vCardIdGen.next().value;
|
||||||
|
labelEls[i].textContent = stringBundle.GetStringFromName(
|
||||||
|
`propertyCustom${i + 1}`
|
||||||
|
);
|
||||||
|
labelEls[i].htmlFor = inputId;
|
||||||
|
this.inputEls[i].id = inputId;
|
||||||
|
}
|
||||||
|
this.fromVCardPropertyEntryToUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnectedCallback() {
|
||||||
|
if (!this.isConnected) {
|
||||||
|
this.inputEls = null;
|
||||||
|
this.vCardPropertyEntries = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fromVCardPropertyEntryToUI() {
|
||||||
|
for (let i = 0; i < 4; i++) {
|
||||||
|
this.inputEls[i].value = this.vCardPropertyEntries[i].value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fromUIToVCardPropertyEntry() {
|
||||||
|
for (let i = 0; i < 4; i++) {
|
||||||
|
this.vCardPropertyEntries[i].value = this.inputEls[i].value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("vcard-custom", VCardCustomComponent);
|
|
@ -2,11 +2,11 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, you can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, you can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
/* globals VCardAdrComponent, VCardEmailComponent, VCardIMPPComponent,
|
/* globals VCardAdrComponent, VCardCustomComponent, VCardEmailComponent,
|
||||||
VCardNComponent, VCardFNComponent, VCardNickNameComponent,
|
VCardIMPPComponent, VCardNComponent, VCardFNComponent,
|
||||||
VCardNoteComponent, VCardOrgComponent, VCardRoleComponent,
|
VCardNickNameComponent, VCardNoteComponent, VCardOrgComponent,
|
||||||
VCardSpecialDateComponent, VCardTelComponent, VCardTitleComponent,
|
VCardRoleComponent, VCardSpecialDateComponent, VCardTelComponent,
|
||||||
VCardTZComponent, VCardURLComponent */
|
VCardTitleComponent, VCardTZComponent, VCardURLComponent */
|
||||||
|
|
||||||
ChromeUtils.defineModuleGetter(
|
ChromeUtils.defineModuleGetter(
|
||||||
this,
|
this,
|
||||||
|
@ -106,6 +106,15 @@ class VCardEdit extends HTMLElement {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (let i = 1; i <= 4; i++) {
|
||||||
|
if (!this._vCardProperties.getFirstEntry(`x-custom${i}`)) {
|
||||||
|
this._vCardProperties.addEntry(
|
||||||
|
new VCardPropertyEntry(`x-custom${i}`, {}, "text", "")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.updateView();
|
this.updateView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,13 +132,28 @@ class VCardEdit extends HTMLElement {
|
||||||
|
|
||||||
this.addFieldsetActions();
|
this.addFieldsetActions();
|
||||||
|
|
||||||
this._orgComponent = null;
|
|
||||||
|
|
||||||
// Insert the vCard property entries.
|
// Insert the vCard property entries.
|
||||||
for (let vCardPropertyEntry of this.vCardProperties.entries) {
|
for (let vCardPropertyEntry of this.vCardProperties.entries) {
|
||||||
this.insertVCardElement(vCardPropertyEntry, false);
|
this.insertVCardElement(vCardPropertyEntry, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let customProperties = ["x-custom1", "x-custom2", "x-custom3", "x-custom4"];
|
||||||
|
if (
|
||||||
|
customProperties.some(name => this.vCardProperties.getFirstValue(name))
|
||||||
|
) {
|
||||||
|
// If one of these properties has a value, display all of them.
|
||||||
|
let customFieldset = this.querySelector("#addr-book-edit-custom");
|
||||||
|
let customEl =
|
||||||
|
customFieldset.querySelector("vcard-custom") ||
|
||||||
|
new VCardCustomComponent();
|
||||||
|
customEl.vCardPropertyEntries = customProperties.map(name =>
|
||||||
|
this._vCardProperties.getFirstEntry(name)
|
||||||
|
);
|
||||||
|
let addCustom = document.getElementById("vcard-add-custom");
|
||||||
|
customFieldset.insertBefore(customEl, addCustom);
|
||||||
|
addCustom.hidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
let nameEl = this.querySelector("vcard-n");
|
let nameEl = this.querySelector("vcard-n");
|
||||||
this.firstName = nameEl.firstNameEl.querySelector("input");
|
this.firstName = nameEl.firstNameEl.querySelector("input");
|
||||||
this.lastName = nameEl.lastNameEl.querySelector("input");
|
this.lastName = nameEl.lastNameEl.querySelector("input");
|
||||||
|
@ -538,6 +562,7 @@ class VCardEdit extends HTMLElement {
|
||||||
saveVCard() {
|
saveVCard() {
|
||||||
for (let node of [
|
for (let node of [
|
||||||
...this.querySelectorAll("vcard-adr"),
|
...this.querySelectorAll("vcard-adr"),
|
||||||
|
...this.querySelectorAll("vcard-custom"),
|
||||||
...document.getElementById("vcard-email").children,
|
...document.getElementById("vcard-email").children,
|
||||||
...this.querySelectorAll("vcard-fn"),
|
...this.querySelectorAll("vcard-fn"),
|
||||||
...this.querySelectorAll("vcard-impp"),
|
...this.querySelectorAll("vcard-impp"),
|
||||||
|
@ -570,6 +595,13 @@ class VCardEdit extends HTMLElement {
|
||||||
) {
|
) {
|
||||||
emailEntries[0].params.pref = "1";
|
emailEntries[0].params.pref = "1";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (let i = 1; i <= 4; i++) {
|
||||||
|
let entry = this._vCardProperties.getFirstEntry(`x-custom${i}`);
|
||||||
|
if (!entry.value) {
|
||||||
|
this._vCardProperties.removeEntry(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -707,6 +739,21 @@ class VCardEdit extends HTMLElement {
|
||||||
this.registerAddButton(addNote, "note", () => {
|
this.registerAddButton(addNote, "note", () => {
|
||||||
addNote.hidden = true;
|
addNote.hidden = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let addCustom = document.getElementById("vcard-add-custom");
|
||||||
|
addCustom.addEventListener("click", event => {
|
||||||
|
let el = new VCardCustomComponent();
|
||||||
|
el.vCardPropertyEntries = [
|
||||||
|
this._vCardProperties.getFirstEntry("x-custom1"),
|
||||||
|
this._vCardProperties.getFirstEntry("x-custom2"),
|
||||||
|
this._vCardProperties.getFirstEntry("x-custom3"),
|
||||||
|
this._vCardProperties.getFirstEntry("x-custom4"),
|
||||||
|
];
|
||||||
|
addCustom.parentNode.insertBefore(el, addCustom);
|
||||||
|
|
||||||
|
this.moveFocusIntoElement(el);
|
||||||
|
addCustom.hidden = true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
<!-- Scripts -->
|
<!-- Scripts -->
|
||||||
<script src="chrome://messenger/content/addressbook/edit/adr.js"></script>
|
<script src="chrome://messenger/content/addressbook/edit/adr.js"></script>
|
||||||
|
<script src="chrome://messenger/content/addressbook/edit/custom.js"></script>
|
||||||
<script src="chrome://messenger/content/addressbook/edit/org.js"></script>
|
<script src="chrome://messenger/content/addressbook/edit/org.js"></script>
|
||||||
<script src="chrome://messenger/content/addressbook/edit/email.js"></script>
|
<script src="chrome://messenger/content/addressbook/edit/email.js"></script>
|
||||||
<script src="chrome://messenger/content/addressbook/edit/fn.js"></script>
|
<script src="chrome://messenger/content/addressbook/edit/fn.js"></script>
|
||||||
|
@ -126,6 +127,14 @@
|
||||||
class="addr-book-edit-fieldset-button"
|
class="addr-book-edit-fieldset-button"
|
||||||
type="button"></button>
|
type="button"></button>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
<!-- Custom -->
|
||||||
|
<fieldset id="addr-book-edit-custom" class="addr-book-edit-fieldset fieldset-reset">
|
||||||
|
<legend data-l10n-id="vcard-custom-header"/>
|
||||||
|
<button id="vcard-add-custom"
|
||||||
|
data-l10n-id="vcard-custom-add"
|
||||||
|
class="addr-book-edit-fieldset-button"
|
||||||
|
type="button"></button>
|
||||||
|
</fieldset>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- Individual fields -->
|
<!-- Individual fields -->
|
||||||
|
@ -322,6 +331,26 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<!-- Custom -->
|
||||||
|
<template id="template-vcard-edit-custom">
|
||||||
|
<div class="vcard-adr-inputs">
|
||||||
|
<label for="custom1"/>
|
||||||
|
<input type="text"/>
|
||||||
|
</div>
|
||||||
|
<div class="vcard-adr-inputs">
|
||||||
|
<label for="custom2"/>
|
||||||
|
<input type="text"/>
|
||||||
|
</div>
|
||||||
|
<div class="vcard-adr-inputs">
|
||||||
|
<label for="custom3"/>
|
||||||
|
<input type="text"/>
|
||||||
|
</div>
|
||||||
|
<div class="vcard-adr-inputs">
|
||||||
|
<label for="custom4"/>
|
||||||
|
<input type="text"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template id="template-vcard-edit-type">
|
<template id="template-vcard-edit-type">
|
||||||
<select class="vcard-type-selection">
|
<select class="vcard-type-selection">
|
||||||
<option value="work" data-l10n-id="vcard-entry-type-work"/>
|
<option value="work" data-l10n-id="vcard-entry-type-work"/>
|
||||||
|
|
|
@ -19,6 +19,7 @@ messenger.jar:
|
||||||
content/messenger/addressbook/abView-new.js (content/abView-new.js)
|
content/messenger/addressbook/abView-new.js (content/abView-new.js)
|
||||||
# Edit view
|
# Edit view
|
||||||
content/messenger/addressbook/edit/adr.js (content/vcard-edit/adr.js)
|
content/messenger/addressbook/edit/adr.js (content/vcard-edit/adr.js)
|
||||||
|
content/messenger/addressbook/edit/custom.js (content/vcard-edit/custom.js)
|
||||||
content/messenger/addressbook/edit/edit.js (content/vcard-edit/edit.js)
|
content/messenger/addressbook/edit/edit.js (content/vcard-edit/edit.js)
|
||||||
content/messenger/addressbook/edit/email.js (content/vcard-edit/email.js)
|
content/messenger/addressbook/edit/email.js (content/vcard-edit/email.js)
|
||||||
content/messenger/addressbook/edit/fn.js (content/vcard-edit/fn.js)
|
content/messenger/addressbook/edit/fn.js (content/vcard-edit/fn.js)
|
||||||
|
|
|
@ -72,59 +72,6 @@ add_setup(async function() {
|
||||||
END:VCARD
|
END:VCARD
|
||||||
`)
|
`)
|
||||||
);
|
);
|
||||||
// Card 3.
|
|
||||||
personalBook.addCard(
|
|
||||||
VCardUtils.vCardToAbCard(formatVCard`
|
|
||||||
BEGIN:VCARD
|
|
||||||
EMAIL:xbasic3@invalid
|
|
||||||
ANNIVERSARY:2005
|
|
||||||
END:VCARD
|
|
||||||
`)
|
|
||||||
);
|
|
||||||
// Card 4.
|
|
||||||
personalBook.addCard(
|
|
||||||
VCardUtils.vCardToAbCard(formatVCard`
|
|
||||||
BEGIN:VCARD
|
|
||||||
EMAIL:xbasic4@invalid
|
|
||||||
ANNIVERSARY:2006-06
|
|
||||||
END:VCARD
|
|
||||||
`)
|
|
||||||
);
|
|
||||||
// Card 5.
|
|
||||||
personalBook.addCard(
|
|
||||||
VCardUtils.vCardToAbCard(formatVCard`
|
|
||||||
BEGIN:VCARD
|
|
||||||
EMAIL:xbasic5@invalid
|
|
||||||
ANNIVERSARY:--12
|
|
||||||
END:VCARD
|
|
||||||
`)
|
|
||||||
);
|
|
||||||
// Card 6.
|
|
||||||
personalBook.addCard(
|
|
||||||
VCardUtils.vCardToAbCard(formatVCard`
|
|
||||||
BEGIN:VCARD
|
|
||||||
EMAIL:xbasic6@invalid
|
|
||||||
ANNIVERSARY;VALUE=DATE:--0704
|
|
||||||
END:VCARD
|
|
||||||
`)
|
|
||||||
);
|
|
||||||
// Card 7.
|
|
||||||
personalBook.addCard(
|
|
||||||
VCardUtils.vCardToAbCard(formatVCard`
|
|
||||||
BEGIN:VCARD
|
|
||||||
EMAIL:xbasic7@invalid
|
|
||||||
ANNIVERSARY:---30
|
|
||||||
END:VCARD
|
|
||||||
`)
|
|
||||||
);
|
|
||||||
// Card 8.
|
|
||||||
personalBook.addCard(
|
|
||||||
VCardUtils.vCardToAbCard(formatVCard`
|
|
||||||
BEGIN:VCARD
|
|
||||||
ORG:xbasic8org
|
|
||||||
END:VCARD
|
|
||||||
`)
|
|
||||||
);
|
|
||||||
|
|
||||||
MailServices.accounts.createLocalMailAccount();
|
MailServices.accounts.createLocalMailAccount();
|
||||||
let account = MailServices.accounts.accounts[0];
|
let account = MailServices.accounts.accounts[0];
|
||||||
|
@ -412,84 +359,6 @@ add_task(async function testDisplay() {
|
||||||
items[5].children[1].lastChild.getAttribute("tz"),
|
items[5].children[1].lastChild.getAttribute("tz"),
|
||||||
"Pacific/Auckland"
|
"Pacific/Auckland"
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test card 3:
|
|
||||||
EventUtils.synthesizeMouseAtCenter(cardsList.getRowAtIndex(3), {}, abWindow);
|
|
||||||
await TestUtils.waitForCondition(() =>
|
|
||||||
BrowserTestUtils.is_visible(detailsPane)
|
|
||||||
);
|
|
||||||
Assert.ok(BrowserTestUtils.is_visible(otherInfoSection));
|
|
||||||
items = otherInfoSection.querySelectorAll("li");
|
|
||||||
Assert.equal(items.length, 1);
|
|
||||||
Assert.equal(
|
|
||||||
items[0].children[0].dataset.l10nId,
|
|
||||||
"about-addressbook-entry-name-anniversary"
|
|
||||||
);
|
|
||||||
Assert.equal(items[0].children[1].textContent, "2005");
|
|
||||||
|
|
||||||
// Test card 4:
|
|
||||||
EventUtils.synthesizeMouseAtCenter(cardsList.getRowAtIndex(4), {}, abWindow);
|
|
||||||
await TestUtils.waitForCondition(() =>
|
|
||||||
BrowserTestUtils.is_visible(detailsPane)
|
|
||||||
);
|
|
||||||
Assert.ok(BrowserTestUtils.is_visible(otherInfoSection));
|
|
||||||
items = otherInfoSection.querySelectorAll("li");
|
|
||||||
Assert.equal(items.length, 1);
|
|
||||||
Assert.equal(
|
|
||||||
items[0].children[0].dataset.l10nId,
|
|
||||||
"about-addressbook-entry-name-anniversary"
|
|
||||||
);
|
|
||||||
Assert.equal(items[0].children[1].textContent, "June 2006");
|
|
||||||
|
|
||||||
// Test card 5:
|
|
||||||
EventUtils.synthesizeMouseAtCenter(cardsList.getRowAtIndex(5), {}, abWindow);
|
|
||||||
await TestUtils.waitForCondition(() =>
|
|
||||||
BrowserTestUtils.is_visible(detailsPane)
|
|
||||||
);
|
|
||||||
Assert.ok(BrowserTestUtils.is_visible(otherInfoSection));
|
|
||||||
items = otherInfoSection.querySelectorAll("li");
|
|
||||||
Assert.equal(items.length, 1);
|
|
||||||
Assert.equal(
|
|
||||||
items[0].children[0].dataset.l10nId,
|
|
||||||
"about-addressbook-entry-name-anniversary"
|
|
||||||
);
|
|
||||||
Assert.equal(items[0].children[1].textContent, "December");
|
|
||||||
|
|
||||||
// Test card 6:
|
|
||||||
EventUtils.synthesizeMouseAtCenter(cardsList.getRowAtIndex(6), {}, abWindow);
|
|
||||||
await TestUtils.waitForCondition(() =>
|
|
||||||
BrowserTestUtils.is_visible(detailsPane)
|
|
||||||
);
|
|
||||||
Assert.ok(BrowserTestUtils.is_visible(otherInfoSection));
|
|
||||||
items = otherInfoSection.querySelectorAll("li");
|
|
||||||
Assert.equal(items.length, 1);
|
|
||||||
Assert.equal(
|
|
||||||
items[0].children[0].dataset.l10nId,
|
|
||||||
"about-addressbook-entry-name-anniversary"
|
|
||||||
);
|
|
||||||
Assert.equal(items[0].children[1].textContent, "July 4");
|
|
||||||
|
|
||||||
// Test card 7:
|
|
||||||
EventUtils.synthesizeMouseAtCenter(cardsList.getRowAtIndex(7), {}, abWindow);
|
|
||||||
await TestUtils.waitForCondition(() =>
|
|
||||||
BrowserTestUtils.is_visible(detailsPane)
|
|
||||||
);
|
|
||||||
Assert.ok(BrowserTestUtils.is_visible(otherInfoSection));
|
|
||||||
items = otherInfoSection.querySelectorAll("li");
|
|
||||||
Assert.equal(items.length, 1);
|
|
||||||
Assert.equal(
|
|
||||||
items[0].children[0].dataset.l10nId,
|
|
||||||
"about-addressbook-entry-name-anniversary"
|
|
||||||
);
|
|
||||||
Assert.equal(items[0].children[1].textContent, "30");
|
|
||||||
|
|
||||||
// Test card 8:
|
|
||||||
EventUtils.synthesizeMouseAtCenter(cardsList.getRowAtIndex(8), {}, abWindow);
|
|
||||||
await TestUtils.waitForCondition(() =>
|
|
||||||
BrowserTestUtils.is_visible(detailsPane)
|
|
||||||
);
|
|
||||||
Assert.equal(viewContactName.textContent, "xbasic8org");
|
|
||||||
|
|
||||||
Assert.ok(BrowserTestUtils.is_hidden(selectedCardsSection));
|
Assert.ok(BrowserTestUtils.is_hidden(selectedCardsSection));
|
||||||
|
|
||||||
// Card 0, again, just to prove that everything was cleared properly.
|
// Card 0, again, just to prove that everything was cleared properly.
|
||||||
|
@ -517,6 +386,161 @@ add_task(async function testDisplay() {
|
||||||
await closeAddressBookWindow();
|
await closeAddressBookWindow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the display of dates with various components missing.
|
||||||
|
*/
|
||||||
|
add_task(async function testDates() {
|
||||||
|
let abWindow = await openAddressBookWindow();
|
||||||
|
let otherInfoSection = abWindow.document.getElementById("otherInfo");
|
||||||
|
|
||||||
|
// Year only.
|
||||||
|
|
||||||
|
let yearCard = await addAndDisplayCard(formatVCard`
|
||||||
|
BEGIN:VCARD
|
||||||
|
EMAIL:xbasic3@invalid
|
||||||
|
ANNIVERSARY:2005
|
||||||
|
END:VCARD
|
||||||
|
`);
|
||||||
|
Assert.ok(BrowserTestUtils.is_visible(otherInfoSection));
|
||||||
|
let items = otherInfoSection.querySelectorAll("li");
|
||||||
|
Assert.equal(items.length, 1);
|
||||||
|
Assert.equal(
|
||||||
|
items[0].children[0].dataset.l10nId,
|
||||||
|
"about-addressbook-entry-name-anniversary"
|
||||||
|
);
|
||||||
|
Assert.equal(items[0].children[1].textContent, "2005");
|
||||||
|
|
||||||
|
// Year and month.
|
||||||
|
|
||||||
|
let yearMonthCard = await addAndDisplayCard(formatVCard`
|
||||||
|
BEGIN:VCARD
|
||||||
|
EMAIL:xbasic4@invalid
|
||||||
|
ANNIVERSARY:2006-06
|
||||||
|
END:VCARD
|
||||||
|
`);
|
||||||
|
Assert.ok(BrowserTestUtils.is_visible(otherInfoSection));
|
||||||
|
items = otherInfoSection.querySelectorAll("li");
|
||||||
|
Assert.equal(items.length, 1);
|
||||||
|
Assert.equal(
|
||||||
|
items[0].children[0].dataset.l10nId,
|
||||||
|
"about-addressbook-entry-name-anniversary"
|
||||||
|
);
|
||||||
|
Assert.equal(items[0].children[1].textContent, "June 2006");
|
||||||
|
|
||||||
|
// Month only.
|
||||||
|
let monthCard = await addAndDisplayCard(formatVCard`
|
||||||
|
BEGIN:VCARD
|
||||||
|
EMAIL:xbasic5@invalid
|
||||||
|
ANNIVERSARY:--12
|
||||||
|
END:VCARD
|
||||||
|
`);
|
||||||
|
Assert.ok(BrowserTestUtils.is_visible(otherInfoSection));
|
||||||
|
items = otherInfoSection.querySelectorAll("li");
|
||||||
|
Assert.equal(items.length, 1);
|
||||||
|
Assert.equal(
|
||||||
|
items[0].children[0].dataset.l10nId,
|
||||||
|
"about-addressbook-entry-name-anniversary"
|
||||||
|
);
|
||||||
|
Assert.equal(items[0].children[1].textContent, "December");
|
||||||
|
|
||||||
|
// Month and day.
|
||||||
|
let monthDayCard = await addAndDisplayCard(formatVCard`
|
||||||
|
BEGIN:VCARD
|
||||||
|
EMAIL:xbasic6@invalid
|
||||||
|
ANNIVERSARY;VALUE=DATE:--0704
|
||||||
|
END:VCARD
|
||||||
|
`);
|
||||||
|
Assert.ok(BrowserTestUtils.is_visible(otherInfoSection));
|
||||||
|
items = otherInfoSection.querySelectorAll("li");
|
||||||
|
Assert.equal(items.length, 1);
|
||||||
|
Assert.equal(
|
||||||
|
items[0].children[0].dataset.l10nId,
|
||||||
|
"about-addressbook-entry-name-anniversary"
|
||||||
|
);
|
||||||
|
Assert.equal(items[0].children[1].textContent, "July 4");
|
||||||
|
|
||||||
|
// Day only.
|
||||||
|
let dayCard = await addAndDisplayCard(formatVCard`
|
||||||
|
BEGIN:VCARD
|
||||||
|
EMAIL:xbasic7@invalid
|
||||||
|
ANNIVERSARY:---30
|
||||||
|
END:VCARD
|
||||||
|
`);
|
||||||
|
Assert.ok(BrowserTestUtils.is_visible(otherInfoSection));
|
||||||
|
items = otherInfoSection.querySelectorAll("li");
|
||||||
|
Assert.equal(items.length, 1);
|
||||||
|
Assert.equal(
|
||||||
|
items[0].children[0].dataset.l10nId,
|
||||||
|
"about-addressbook-entry-name-anniversary"
|
||||||
|
);
|
||||||
|
Assert.equal(items[0].children[1].textContent, "30");
|
||||||
|
|
||||||
|
await closeAddressBookWindow();
|
||||||
|
personalBook.deleteCards([
|
||||||
|
yearCard,
|
||||||
|
yearMonthCard,
|
||||||
|
monthCard,
|
||||||
|
monthDayCard,
|
||||||
|
dayCard,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only an organisation name.
|
||||||
|
*/
|
||||||
|
add_task(async function testOrganisationNameOnly() {
|
||||||
|
let card = await addAndDisplayCard(
|
||||||
|
VCardUtils.vCardToAbCard(formatVCard`
|
||||||
|
BEGIN:VCARD
|
||||||
|
ORG:organisation
|
||||||
|
END:VCARD
|
||||||
|
`)
|
||||||
|
);
|
||||||
|
|
||||||
|
let abWindow = await getAddressBookWindow();
|
||||||
|
let viewContactName = abWindow.document.getElementById("viewContactName");
|
||||||
|
Assert.equal(viewContactName.textContent, "organisation");
|
||||||
|
|
||||||
|
await closeAddressBookWindow();
|
||||||
|
personalBook.deleteCards([card]);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that custom properties (Custom1 etc.) are displayed.
|
||||||
|
*/
|
||||||
|
add_task(async function testCustomProperties() {
|
||||||
|
let card = VCardUtils.vCardToAbCard(formatVCard`
|
||||||
|
BEGIN:VCARD
|
||||||
|
FN:custom person
|
||||||
|
X-CUSTOM3:x-custom three
|
||||||
|
X-CUSTOM4:x-custom four
|
||||||
|
END:VCARD
|
||||||
|
`);
|
||||||
|
card.setProperty("Custom2", "custom two");
|
||||||
|
card.setProperty("Custom4", "custom four");
|
||||||
|
card = await addAndDisplayCard(card);
|
||||||
|
|
||||||
|
let abWindow = await getAddressBookWindow();
|
||||||
|
let otherInfoSection = abWindow.document.getElementById("otherInfo");
|
||||||
|
|
||||||
|
Assert.ok(BrowserTestUtils.is_visible(otherInfoSection));
|
||||||
|
let items = otherInfoSection.querySelectorAll("li");
|
||||||
|
Assert.equal(items.length, 3);
|
||||||
|
// Custom 1 has no value, should not display.
|
||||||
|
// Custom 2 has an old property value, should display that.
|
||||||
|
Assert.equal(items[0].children[0].textContent, "Custom 2");
|
||||||
|
Assert.equal(items[0].children[1].textContent, "custom two");
|
||||||
|
// Custom 3 has a vCard property value, should display that.
|
||||||
|
Assert.equal(items[1].children[0].textContent, "Custom 3");
|
||||||
|
Assert.equal(items[1].children[1].textContent, "x-custom three");
|
||||||
|
// Custom 4 has both types of value, the vCard value should be displayed.
|
||||||
|
Assert.equal(items[2].children[0].textContent, "Custom 4");
|
||||||
|
Assert.equal(items[2].children[1].textContent, "x-custom four");
|
||||||
|
|
||||||
|
await closeAddressBookWindow();
|
||||||
|
personalBook.deleteCards([card]);
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks that the edit button is hidden for read-only contacts.
|
* Checks that the edit button is hidden for read-only contacts.
|
||||||
*/
|
*/
|
||||||
|
@ -663,7 +687,7 @@ add_task(async function testReadOnlyActions() {
|
||||||
// Check contacts with All Address Books displayed.
|
// Check contacts with All Address Books displayed.
|
||||||
|
|
||||||
openAllAddressBooks();
|
openAllAddressBooks();
|
||||||
Assert.equal(cardsList.view.rowCount, 12);
|
Assert.equal(cardsList.view.rowCount, 6);
|
||||||
Assert.ok(BrowserTestUtils.is_hidden(detailsPane));
|
Assert.ok(BrowserTestUtils.is_hidden(detailsPane));
|
||||||
|
|
||||||
// Basic person from Personal Address Books.
|
// Basic person from Personal Address Books.
|
||||||
|
@ -818,6 +842,30 @@ add_task(async function testGoogleEscaping() {
|
||||||
await promiseDirectoryRemoved(googleBook.URI);
|
await promiseDirectoryRemoved(googleBook.URI);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function addAndDisplayCard(card) {
|
||||||
|
if (typeof card == "string") {
|
||||||
|
card = VCardUtils.vCardToAbCard(card);
|
||||||
|
}
|
||||||
|
card = personalBook.addCard(card);
|
||||||
|
|
||||||
|
let abWindow = await openAddressBookWindow();
|
||||||
|
let abDocument = abWindow.document;
|
||||||
|
let cardsList = abDocument.getElementById("cards");
|
||||||
|
let detailsPane = abDocument.getElementById("detailsPane");
|
||||||
|
|
||||||
|
let index = cardsList.view.getIndexForUID(card.UID);
|
||||||
|
EventUtils.synthesizeMouseAtCenter(
|
||||||
|
cardsList.getRowAtIndex(index),
|
||||||
|
{},
|
||||||
|
abWindow
|
||||||
|
);
|
||||||
|
await TestUtils.waitForCondition(() =>
|
||||||
|
BrowserTestUtils.is_visible(detailsPane)
|
||||||
|
);
|
||||||
|
|
||||||
|
return card;
|
||||||
|
}
|
||||||
|
|
||||||
async function checkActionButtons(
|
async function checkActionButtons(
|
||||||
primaryEmail,
|
primaryEmail,
|
||||||
displayName,
|
displayName,
|
||||||
|
|
|
@ -184,6 +184,11 @@ function getFields(entryName, addIfNeeded = false, count) {
|
||||||
addButtonId = "vcard-add-org";
|
addButtonId = "vcard-add-org";
|
||||||
expectFocusSelector = "vcard-title:last-of-type input";
|
expectFocusSelector = "vcard-title:last-of-type input";
|
||||||
break;
|
break;
|
||||||
|
case "custom":
|
||||||
|
fieldsSelector = "vcard-custom";
|
||||||
|
addButtonId = "vcard-add-custom";
|
||||||
|
expectFocusSelector = "vcard-custom:last-of-type input";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error("entryName not found");
|
throw new Error("entryName not found");
|
||||||
}
|
}
|
||||||
|
@ -2827,6 +2832,72 @@ add_task(async function test_special_date_field() {
|
||||||
await closeAddressBookWindow();
|
await closeAddressBookWindow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that custom properties (Custom1 etc.) are editable.
|
||||||
|
*/
|
||||||
|
add_task(async function testCustomProperties() {
|
||||||
|
let card = VCardUtils.vCardToAbCard(formatVCard`
|
||||||
|
BEGIN:VCARD
|
||||||
|
FN:custom person
|
||||||
|
X-CUSTOM3:x-custom three
|
||||||
|
X-CUSTOM4:x-custom four
|
||||||
|
END:VCARD
|
||||||
|
`);
|
||||||
|
card.setProperty("Custom2", "custom two");
|
||||||
|
card.setProperty("Custom4", "custom four");
|
||||||
|
card = personalBook.addCard(card);
|
||||||
|
|
||||||
|
let abWindow = await openAddressBookWindow();
|
||||||
|
let abDocument = abWindow.document;
|
||||||
|
let cardsList = abDocument.getElementById("cards");
|
||||||
|
let detailsPane = abDocument.getElementById("detailsPane");
|
||||||
|
let editButton = abDocument.getElementById("editButton");
|
||||||
|
let saveEditButton = abDocument.getElementById("saveEditButton");
|
||||||
|
|
||||||
|
let index = cardsList.view.getIndexForUID(card.UID);
|
||||||
|
EventUtils.synthesizeMouseAtCenter(
|
||||||
|
cardsList.getRowAtIndex(index),
|
||||||
|
{},
|
||||||
|
abWindow
|
||||||
|
);
|
||||||
|
await TestUtils.waitForCondition(() =>
|
||||||
|
BrowserTestUtils.is_visible(detailsPane)
|
||||||
|
);
|
||||||
|
|
||||||
|
EventUtils.synthesizeMouseAtCenter(editButton, {}, abWindow);
|
||||||
|
await inEditingMode();
|
||||||
|
|
||||||
|
let customField = getFields("custom")[0];
|
||||||
|
let inputs = customField.querySelectorAll("input");
|
||||||
|
Assert.equal(inputs.length, 4);
|
||||||
|
Assert.equal(inputs[0].value, "");
|
||||||
|
Assert.equal(inputs[1].value, "custom two");
|
||||||
|
Assert.equal(inputs[2].value, "x-custom three");
|
||||||
|
Assert.equal(inputs[3].value, "x-custom four");
|
||||||
|
|
||||||
|
inputs[0].value = "x-custom one";
|
||||||
|
inputs[1].value = "x-custom two";
|
||||||
|
inputs[3].value = "";
|
||||||
|
|
||||||
|
EventUtils.synthesizeMouseAtCenter(saveEditButton, {}, abWindow);
|
||||||
|
await notInEditingMode(editButton);
|
||||||
|
|
||||||
|
card = personalBook.childCards.find(c => c.UID == card.UID);
|
||||||
|
checkCardValues(card, {
|
||||||
|
Custom2: null,
|
||||||
|
Custom4: null,
|
||||||
|
});
|
||||||
|
checkVCardValues(card, {
|
||||||
|
"x-custom1": [{ value: "x-custom one" }],
|
||||||
|
"x-custom2": [{ value: "x-custom two" }],
|
||||||
|
"x-custom3": [{ value: "x-custom three" }],
|
||||||
|
"x-custom4": [],
|
||||||
|
});
|
||||||
|
|
||||||
|
await closeAddressBookWindow();
|
||||||
|
personalBook.deleteCards([card]);
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that we correctly fix Google's bad escaping of colons in values, and
|
* Tests that we correctly fix Google's bad escaping of colons in values, and
|
||||||
* other characters in URI values.
|
* other characters in URI values.
|
||||||
|
|
|
@ -146,3 +146,9 @@ vcard-org-title = Title
|
||||||
vcard-org-role = Role
|
vcard-org-role = Role
|
||||||
|
|
||||||
vcard-org-org = Organization
|
vcard-org-org = Organization
|
||||||
|
|
||||||
|
# Custom properties
|
||||||
|
|
||||||
|
vcard-custom-header = Custom Properties
|
||||||
|
|
||||||
|
vcard-custom-add = Add custom properties
|
||||||
|
|
|
@ -505,6 +505,10 @@ var typeMap = {
|
||||||
"tel.cell": singleTextProperty("CellularNumber", "tel", { type: "cell" }),
|
"tel.cell": singleTextProperty("CellularNumber", "tel", { type: "cell" }),
|
||||||
"url.work": singleTextProperty("WebPage1", "url", { type: "work" }, "url"),
|
"url.work": singleTextProperty("WebPage1", "url", { type: "work" }, "url"),
|
||||||
"url.home": singleTextProperty("WebPage2", "url", { type: "home" }, "url"),
|
"url.home": singleTextProperty("WebPage2", "url", { type: "home" }, "url"),
|
||||||
|
"x-custom1": singleTextProperty("Custom1", "x-custom1"),
|
||||||
|
"x-custom2": singleTextProperty("Custom2", "x-custom2"),
|
||||||
|
"x-custom3": singleTextProperty("Custom3", "x-custom3"),
|
||||||
|
"x-custom4": singleTextProperty("Custom4", "x-custom4"),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -12,5 +12,9 @@ FN:contact number two
|
||||||
NOTE:here's some unicode text…
|
NOTE:here's some unicode text…
|
||||||
TITLE:"worker"
|
TITLE:"worker"
|
||||||
N:two;contact;;;
|
N:two;contact;;;
|
||||||
|
X-CUSTOM1;VALUE=TEXT:custom\, 1
|
||||||
|
X-CUSTOM2;VALUE=TEXT:custom 2
|
||||||
|
X-CUSTOM3;VALUE=TEXT:custom
3
|
||||||
|
X-CUSTOM4;VALUE=TEXT:custom\n4
|
||||||
UID:yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy
|
UID:yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy
|
||||||
END:VCARD
|
END:VCARD
|
||||||
|
|
|
@ -16,6 +16,9 @@ var { AppConstants } = ChromeUtils.import(
|
||||||
var { MailServices } = ChromeUtils.import(
|
var { MailServices } = ChromeUtils.import(
|
||||||
"resource:///modules/MailServices.jsm"
|
"resource:///modules/MailServices.jsm"
|
||||||
);
|
);
|
||||||
|
var { VCardPropertyEntry } = ChromeUtils.import(
|
||||||
|
"resource:///modules/VCardUtils.jsm"
|
||||||
|
);
|
||||||
|
|
||||||
async function subtest(cardConstructor) {
|
async function subtest(cardConstructor) {
|
||||||
let dirPrefId = MailServices.ab.newAddressBook(
|
let dirPrefId = MailServices.ab.newAddressBook(
|
||||||
|
@ -35,6 +38,10 @@ async function subtest(cardConstructor) {
|
||||||
|
|
||||||
let contact2 = cardConstructor();
|
let contact2 = cardConstructor();
|
||||||
contact2.UID = "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy";
|
contact2.UID = "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy";
|
||||||
|
contact2.setProperty("Custom1", "custom, 1");
|
||||||
|
contact2.setProperty("Custom2", "custom\t2");
|
||||||
|
contact2.setProperty("Custom3", "custom\r3");
|
||||||
|
contact2.setProperty("Custom4", "custom\n4");
|
||||||
contact2.displayName = "contact number two";
|
contact2.displayName = "contact number two";
|
||||||
contact2.firstName = "contact";
|
contact2.firstName = "contact";
|
||||||
contact2.lastName = "two";
|
contact2.lastName = "two";
|
||||||
|
@ -46,10 +53,6 @@ async function subtest(cardConstructor) {
|
||||||
contact2.setProperty("JobTitle", `"worker"`);
|
contact2.setProperty("JobTitle", `"worker"`);
|
||||||
contact2.setProperty("Notes", "here's some unicode text…");
|
contact2.setProperty("Notes", "here's some unicode text…");
|
||||||
}
|
}
|
||||||
contact2.setProperty("Custom1", "custom, 1");
|
|
||||||
contact2.setProperty("Custom2", "custom\t2");
|
|
||||||
contact2.setProperty("Custom3", "custom\r3");
|
|
||||||
contact2.setProperty("Custom4", "custom\n4");
|
|
||||||
contact2 = book.addCard(contact2);
|
contact2 = book.addCard(contact2);
|
||||||
|
|
||||||
let list = Cc["@mozilla.org/addressbook/directoryproperty;1"].createInstance(
|
let list = Cc["@mozilla.org/addressbook/directoryproperty;1"].createInstance(
|
||||||
|
|
|
@ -200,13 +200,17 @@ add_task(function testFromToPropertyMap() {
|
||||||
["LastName", "Test"],
|
["LastName", "Test"],
|
||||||
["FirstName", "Mike"],
|
["FirstName", "Mike"],
|
||||||
["PrimaryEmail", "mike@test.invalid"],
|
["PrimaryEmail", "mike@test.invalid"],
|
||||||
|
["Custom1", "custom one"],
|
||||||
|
["Custom2", "custom two"],
|
||||||
|
["Custom3", "custom three"],
|
||||||
|
["Custom4", "custom four"],
|
||||||
];
|
];
|
||||||
let properties = VCardProperties.fromPropertyMap(
|
let properties = VCardProperties.fromPropertyMap(
|
||||||
new Map(inProperties),
|
new Map(inProperties),
|
||||||
"3.0"
|
"3.0"
|
||||||
);
|
);
|
||||||
|
|
||||||
Assert.equal(properties.entries.length, 4, "entry count");
|
Assert.equal(properties.entries.length, 8, "entry count");
|
||||||
propertyEqual(
|
propertyEqual(
|
||||||
properties.getFirstEntry("version"),
|
properties.getFirstEntry("version"),
|
||||||
{
|
{
|
||||||
|
@ -247,9 +251,49 @@ add_task(function testFromToPropertyMap() {
|
||||||
},
|
},
|
||||||
"email entry"
|
"email entry"
|
||||||
);
|
);
|
||||||
|
propertyEqual(
|
||||||
|
properties.getFirstEntry("x-custom1"),
|
||||||
|
{
|
||||||
|
name: "x-custom1",
|
||||||
|
params: {},
|
||||||
|
type: "text",
|
||||||
|
value: "custom one",
|
||||||
|
},
|
||||||
|
"custom1 entry"
|
||||||
|
);
|
||||||
|
propertyEqual(
|
||||||
|
properties.getFirstEntry("x-custom2"),
|
||||||
|
{
|
||||||
|
name: "x-custom2",
|
||||||
|
params: {},
|
||||||
|
type: "text",
|
||||||
|
value: "custom two",
|
||||||
|
},
|
||||||
|
"custom2 entry"
|
||||||
|
);
|
||||||
|
propertyEqual(
|
||||||
|
properties.getFirstEntry("x-custom3"),
|
||||||
|
{
|
||||||
|
name: "x-custom3",
|
||||||
|
params: {},
|
||||||
|
type: "text",
|
||||||
|
value: "custom three",
|
||||||
|
},
|
||||||
|
"custom3 entry"
|
||||||
|
);
|
||||||
|
propertyEqual(
|
||||||
|
properties.getFirstEntry("x-custom4"),
|
||||||
|
{
|
||||||
|
name: "x-custom4",
|
||||||
|
params: {},
|
||||||
|
type: "text",
|
||||||
|
value: "custom four",
|
||||||
|
},
|
||||||
|
"custom4 entry"
|
||||||
|
);
|
||||||
|
|
||||||
let outProperties = properties.toPropertyMap();
|
let outProperties = properties.toPropertyMap();
|
||||||
Assert.equal(outProperties.size, 4, "property count");
|
Assert.equal(outProperties.size, 8, "property count");
|
||||||
for (let [key, value] of inProperties) {
|
for (let [key, value] of inProperties) {
|
||||||
Assert.equal(outProperties.get(key), value, `${key} property`);
|
Assert.equal(outProperties.get(key), value, `${key} property`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,12 +31,12 @@
|
||||||
"TEL;TYPE=cell;VALUE=TEXT:567-890-1234",
|
"TEL;TYPE=cell;VALUE=TEXT:567-890-1234",
|
||||||
"URL;TYPE=work;VALUE=URL:http://127.0.0.1",
|
"URL;TYPE=work;VALUE=URL:http://127.0.0.1",
|
||||||
"URL;TYPE=home;VALUE=URL:http://localhost",
|
"URL;TYPE=home;VALUE=URL:http://localhost",
|
||||||
|
"X-CUSTOM1;VALUE=TEXT:Custom Field 1",
|
||||||
|
"X-CUSTOM2;VALUE=TEXT:Custom Field 2",
|
||||||
|
"X-CUSTOM3;VALUE=TEXT:Custom Field 3",
|
||||||
|
"X-CUSTOM4;VALUE=TEXT:Custom Field 4",
|
||||||
"UID:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
"UID:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||||
],
|
]
|
||||||
"Custom1": "Custom Field 1",
|
|
||||||
"Custom2": "Custom Field 2",
|
|
||||||
"Custom3": "Custom Field 3",
|
|
||||||
"Custom4": "Custom Field 4"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"bug_263304": [
|
"bug_263304": [
|
||||||
|
|
Загрузка…
Ссылка в новой задаче