dom/contacts/tests/test_contacts_basics.html
author Peter Van der Beken <peterv@propagandism.org>
Fri, 24 Aug 2012 09:32:26 -0700
changeset 109357 dc3f29a730b10ace9129d2605c7a40822ee8121f
parent 109041 cc589462f4ca7879fac34b7a0c48f2d9eacc287c
child 114776 1f7c4fae49c0d80075e7b0380c4b841a5ed30ab0
permissions -rw-r--r--
Bug 753517 part 5. Enable the list IC for new DOM bindings too. r=bz.

<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id={674720}
-->
<head>
  <title>Test for Bug {674720} WebContacts</title>
  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>

<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={674720}">Mozilla Bug {674720}</a>
<p id="display"></p>
<div id="content" style="display: none">

</div>
<pre id="test">
<script class="testbody" type="text/javascript">

"use strict";

var comp = SpecialPowers.wrap(Components);
comp.utils.import("resource://gre/modules/ContactService.jsm");
comp.utils.import("resource://gre/modules/PermissionPromptHelper.jsm");
SpecialPowers.setBoolPref("dom.mozContacts.enabled", true);
SpecialPowers.addPermission("contacts", true, document);

// For Sorting
var c1 = {
  name: "a",
  familyName: ["a"],
  givenName: ["a"],
};

var c2 = {
  name: "b",
  familyName: ["b"],
  givenName: ["b"],
};

var c3 = {
  name: "c",
  familyName: ["c","x"],
  givenName: ["c","x"],
};

var c4 = {
  name: "d",
  familyName: ["d","e"],
  givenName: ["d","e"],
};

var c5 = {
  name: "empty"
};

var adr1 = {
  type: "work",
  streetAddress: "street 1",
  locality: "locality 1",
  region: "region 1",
  postalCode: "postal code 1",
  countryName: "country 1"
};

var adr2 = {
  type: "home, fax",
  streetAddress: "street2",
  locality: "locality2",
  region: "region2",
  postalCode: "postal code2",
  countryName: "country2"
};

var properties1 = {
  name: "Testname1",
  familyName: ["TestFamilyName","Wagner"],
  givenName: ["Test1","Test2"],
  nickname: "nicktest",
  tel: [{type: ["work"], value: "123456", carrier: "testCarrier"} , {type: ["home", "fax"], value: "+9-876-5432"}],
  adr: adr1,
  email: [{type: ["work"], value: "x@y.com"}]
};

var properties2 = {
  name: ["dummyName", "dummyName2"],
  familyName: "dummyFamilyName",
  givenName: "dummyGivenName",
  honorificPrefix: ["dummyHonorificPrefix","dummyHonorificPrefix2"],
  honorificSuffix: "dummyHonorificSuffix",
  additionalName: "dummyadditionalName",
  nickname: "dummyNickname",
  tel: [{type: ["test"], value: "123456789", carrier: "myCarrier"},{type: ["home", "custom"], value: "234567890"}],
  email: [{type: ["test"], value: "a@b.c"}, {value: "b@c.d"}],
  adr: [adr1, adr2],
  impp: [{type: ["aim"], value:"im1"}, {value: "im2"}],
  org: ["org1", "org2"],
  jobTitle: ["boss", "superboss"],
  bday: new Date("1980, 12, 01"),
  note: "test note",
  category: ["cat1", "cat2"],
  url: [{type: ["work", "work2"], value: "www.1.com"}, {value:"www2.com"}],
  anniversary: new Date("2000, 12, 01"),
  sex: "male",
  genderIdentity: "test"
};

var sample_id1;
var sample_id2;

var createResult1;
var createResult2;

var findResult1;
var findResult2;

function clearTemps() {
  sample_id1 = null;
  sample_id2 = null;
  createResult1 = null;
  createResult2 = null;
  findResult1 = null;
  findResult2 = null;
}

function onUnwantedSuccess() {
  ok(false, "onUnwantedSuccess: shouldn't get here");
}

function onFailure() {
  ok(false, "in on Failure!");
}

function checkStr(str1, str2, msg) {
  if (str1)
    ok(typeof str1 == "string" ? [str1] : str1, (typeof str2 == "string") ? [str2] : str2, msg);
}

function checkAddress(adr1, adr2) {
  checkStr(adr1.type, adr2.type, "Same type");
  checkStr(adr1.streetAddress, adr2.streetAddress, "Same streetAddress");
  checkStr(adr1.locality, adr2.locality, "Same locality");
  checkStr(adr1.region, adr2.region, "Same region");
  checkStr(adr1.postalCode, adr2.postalCode, "Same postalCode");
  checkStr(adr1.countryName, adr2.countryName, "Same countryName");
}

function checkTel(tel1, tel2) {
  checkStr(tel1.type, tel2.type, "Same type");
  checkStr(tel1.value, tel2.value, "Same value");
  checkStr(tel1.carrier, tel2.carrier, "Same carrier");
}

function checkField(field1, field2) {
  checkStr(field1.type, field2.type, "Same type");
  checkStr(field1.value, field2.value, "Same value");
}

function checkContacts(contact1, contact2) {
  checkStr(contact1.name, contact2.name, "Same name");
  checkStr(contact1.honorificPrefix, contact2.honorificPrefix, "Same honorificPrefix");
  checkStr(contact1.givenName, contact2.givenName, "Same givenName");
  checkStr(contact1.additionalName, contact2.additionalName, "Same additionalName");
  checkStr(contact1.familyName, contact2.familyName, "Same familyName");
  checkStr(contact1.honorificSuffix, contact2.honorificSuffix, "Same honorificSuffix");
  checkStr(contact1.nickname, contact2.nickname, "Same nickname");
  checkStr(contact1.category, contact2.category, "Same category");
  checkStr(contact1.org, contact2.org, "Same org");
  checkStr(contact1.jobTitle, contact2.jobTitle, "Same jobTitle");
  is(contact1.bday ? contact1.bday.valueOf() : null, contact2.bday ? contact2.bday.valueOf() : null, "Same birthday");
  checkStr(contact1.note, contact2.note, "Same note");
  is(contact1.anniversary ? contact1.anniversary.valueOf() : null , contact2.anniversary ? contact2.anniversary.valueOf() : null, "Same anniversary");
  is(contact1.sex, contact2.sex, "Same sex");
  is(contact1.genderIdentity, contact2.genderIdentity, "Same genderIdentity");

  for (var i in contact1.email) {
    if (contact1.email) {
      ok(contact2.email != null, "conatct2.email exists");
    }
    if (contact2.email) {
      ok(contact1.email != null, "conatct1.email exists");
    }
    checkField(contact1.email[i], contact2.email[i]);
  }
  for (var i in contact1.adr) {
    if (contact1.adr) {
      ok(contact2.adr != null, "conatct2.adr exists");
    }
    if (contact2.adr) {
      ok(contact1.adr != null, "conatct1.adr exists");
    }
    checkAddress(contact1.adr[i], contact2.adr[i]);
  }
  for (var i in contact1.tel) {
    if (contact1.tel) {
      ok(contact2.tel != null, "conatct2.tel exists");
    }
    if (contact2.tel) {
      ok(contact1.tel != null, "conatct1.tel exists");
    }
    checkTel(contact1.tel[i], contact2.tel[i]);
  }
  for (var i in contact1.url) {
    if (contact1.url) {
      ok(contact2.url != null, "conatct2.url exists");
    }
    if (contact2.url) {
      ok(contact1.url != null, "conatct1.url exists");
    }
    checkField(contact1.url[i], contact2.url[i]);
  }
  for (var i in contact1.impp) {
    if (contact1.impp) {
      ok(contact2.impp != null, "conatct2.impp exists");
    }
    if (contact2.impp) {
      ok(contact1.impp != null, "conatct1.impp exists");
    }
    checkField(contact1.impp[i], contact2.impp[i]);
  }
}

var req;
var index = 0;

var mozContacts = window.navigator.mozContacts

var steps = [
  function () {
    ok(true, "Deleting database");
    req = mozContacts.clear();
    req.onsuccess = function () {
      ok(true, "Deleted the database");
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving all contacts");
    req = mozContacts.find({});
    req.onsuccess = function () {
      ok(req.result.length == 0, "Empty database is empty.");
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Adding empty contact");
    createResult1 = new mozContact();
    createResult1.init({});
    req = navigator.mozContacts.save(createResult1);
    req.onsuccess = function () {
      ok(createResult1.id, "The contact now has an ID.");
      sample_id1 = createResult1.id;
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving all contacts");
    req = mozContacts.find({});
    req.onsuccess = function () {
      ok(req.result.length == 1, "One contact.");
      findResult1 = req.result[0];
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Deleting empty contact");
    req = navigator.mozContacts.remove(findResult1);
    req.onsuccess = function () {
      var req2 = mozContacts.find({});
      req2.onsuccess = function () {
        ok(req2.result.length == 0, "Empty Database.");
        clearTemps();
        next();
      }
      req2.onerror = onFailure;
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Adding a new contact1");
    createResult1 = new mozContact();
    createResult1.init(properties1);

    mozContacts.oncontactchange = function(event) {
      is(event.contactID, createResult1.id, "Same contactID");
      is(event.reason, "create", "Same reason");
    }

    req = navigator.mozContacts.save(createResult1);
    req.onsuccess = function () {
      ok(createResult1.id, "The contact now has an ID.");
      sample_id1 = createResult1.id;
      checkContacts(properties1, createResult1);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving by substring");
    var options = {filterBy: ["name"],
                   filterOp: "contains",
                   filterValue: properties1.name.substring(0,3)};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 1, "Found exactly 1 contact.");
      findResult1 = req.result[0];
      ok(findResult1.id == sample_id1, "Same ID");
      checkContacts(createResult1, properties1);
      dump("findResult: " + JSON.stringify(findResult1) + "\n");
      // Some manual testing. Testint the testfunctions
      // tel: [{type: ["work"], value: "123456", carrier: "testCarrier"} , {type: ["home", "fax"], value: "+9-876-5432"}],
      is(findResult1.tel[0].carrier, "testCarrier", "Same Carrier");
      is(findResult1.tel[0].type, "work", "Same type");
      is(findResult1.tel[0].value, "123456", "Same Value");
      is(findResult1.tel[1].type[1], "fax", "Same type");
      is(findResult1.tel[1].value, "+9-876-5432", "Same Value");

      is(findResult1.adr[0].countryName, "country 1", "Same country");

      // email: [{type: ["work"], value: "x@y.com"}]
      is(findResult1.email[0].type, "work", "Same Type");
      is(findResult1.email[0].value, "x@y.com", "Same Value");
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Searching for exact email");
    var options = {filterBy: ["email"],
                   filterOp: "equals",
                   filterValue: properties1.email[0].value};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 1, "Found exactly 1 contact.");
      findResult1 = req.result[0];
      ok(findResult1.id == sample_id1, "Same ID");
      checkContacts(findResult1, createResult1);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving by substring and update");
    mozContacts.oncontactchange = function(event) {
       is(event.contactID, findResult1.id, "Same contactID");
       is(event.reason, "update", "Same reason");
     }
    var options = {filterBy: ["name"],
                   filterOp: "contains",
                   filterValue: properties1.name.substring(0,3)};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 1, "Found exactly 1 contact.");
      findResult1 = req.result[0];
      findResult1.jobTitle = ["new Job"];
      ok(findResult1.id == sample_id1, "Same ID");
      checkContacts(createResult1, properties1);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Adding a new contact");
    mozContacts.oncontactchange = function(event) {
       is(event.contactID, createResult2.id, "Same contactID");
       is(event.reason, "create", "Same reason");
     }
    createResult2 = new mozContact();
    createResult2.init({name: "newName"});
    req = navigator.mozContacts.save(createResult2);
    req.onsuccess = function () {
      ok(createResult2.id, "The contact now has an ID.");
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving by substring");
    var options = {filterBy: ["name"],
                   filterOp: "contains",
                   filterValue: properties1.name.substring(0,3)};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 1, "Found exactly 1 contact.");
      findResult1 = req.result[0];
      checkContacts(createResult1, findResult1);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Remove contact1");
    mozContacts.oncontactchange = function(event) {
      is(event.contactID, createResult1.id, "Same contactID");
      is(event.reason, "remove", "Same reason");
    }
    req = navigator.mozContacts.remove(createResult1);
    req.onsuccess = function () {
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving by substring");
    var options = {filterBy: ["name"],
                   filterOp: "contains",
                   filterValue: properties1.name.substring(0,3)};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 0, "Found no contact.");
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Remove contact2");
    mozContacts.oncontactchange = function(event) {
      is(event.contactID, createResult2.id, "Same contactID");
      is(event.reason, "remove", "Same reason");
    }
    req = navigator.mozContacts.remove(createResult2);
    req.onsuccess = function () {
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving by substring");
    var options = {filterBy: ["name"],
                   filterOp: "contains",
                   filterValue: properties1.name.substring(0,3)};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 0, "Found no contact.");
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Deleting database");
    mozContacts.oncontactchange = function(event) {
      is(event.contactID, "undefined", "Same contactID");
      is(event.reason, "remove", "Same reason");
    }
    req = mozContacts.clear();
    req.onsuccess = function () {
      ok(true, "Deleted the database");
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Adding a new contact with properties1");
    createResult1 = new mozContact();
    createResult1.init(properties1);
    mozContacts.oncontactchange = null;
    req = navigator.mozContacts.save(createResult1);
    req.onsuccess = function () {
      ok(createResult1.id, "The contact now has an ID.");
      sample_id1 = createResult1.id;
      checkContacts(properties1, createResult1);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving by substring tel1");
    var options = {filterBy: ["tel"],
                   filterOp: "contains",
                   filterValue: properties1.tel[1].value.substring(1,5)};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 1, "Found exactly 1 contact.");
      findResult1 = req.result[0];
      ok(findResult1.id == sample_id1, "Same ID");
      checkContacts(createResult1, properties1);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving by substring tel2");
    var options = {filterBy: ["tel"],
                   filterOp: "contains",
                   filterValue: "7654"};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 1, "Found exactly 1 contact.");
      findResult1 = req.result[0];
      ok(findResult1.id == sample_id1, "Same ID");
      checkContacts(createResult1, properties1);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving by substring tel3");
    var options = {filterBy: ["tel"],
                   filterOp: "contains",
                   filterValue: "876-5432"};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 1, "Found exactly 1 contact.");
      findResult1 = req.result[0];
      ok(findResult1.id == sample_id1, "Same ID");
      checkContacts(createResult1, properties1);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving by substring2");
    var options = {filterBy: ["givenName"],
                   filterOp: "contains",
                   filterValue: properties1.givenName[0].substring(0,3)};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 1, "Found exactly 1 contact.");
      findResult1 = req.result[0];
      ok(findResult1.id == sample_id1, "Same ID");
      checkContacts(createResult1, properties1);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving by substring3");
    var options = {filterBy: ["name", "givenName"],
                   filterOp: "contains",
                   filterValue: properties1.givenName[0].substring(0,3)};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 1, "Found exactly 1 contact.");
      findResult1 = req.result[0];
      ok(findResult1.id == sample_id1, "Same ID");
      checkContacts(createResult1, properties1);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving by substring3, Testing multi entry");
    var options = {filterBy: ["name", "givenName", "familyName"],
                   filterOp: "contains",
                   filterValue: properties1.familyName[1].substring(0,3).toLowerCase()};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 1, "Found exactly 1 contact.");
      findResult1 = req.result[0];
      ok(findResult1.id == sample_id1, "Same ID");
      checkContacts(createResult1, properties1);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving all contacts");
    req = mozContacts.find({});
    req.onsuccess = function() {
      ok(req.result.length == 1, "Found exactly 1 contact.");
      findResult1 = req.result[0];
      ok(findResult1.id == sample_id1, "Same ID");
      checkContacts(createResult1, findResult1);
      ok(findResult1.updated, "Has updated field");
      ok(findResult1.published, "Has published field");
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Modifying contact1");
    findResult1.impp = properties1.impp = [{value:"phil impp"}];
    req = navigator.mozContacts.save(findResult1);
    req.onsuccess = function () {
      var req2 = mozContacts.find({});
      req2.onsuccess = function() {
        ok(req2.result.length == 1, "Found exactly 1 contact.");
        findResult2 = req2.result[0];
        ok(findResult2.id == sample_id1, "Same ID");
        checkContacts(findResult2, properties1);
        ok(findResult2.impp.length == 1, "Found exactly 1 IMS info.");
        next();
      };
      req2.onerror = onFailure;
    };
    req.onerror = onFailure;
  },
  function() {
    ok(true, "Saving old contact, should abort!");
    req = mozContacts.save(createResult1);
    req.onsuccess = onUnwantedSuccess;
    req.onerror   = function() { ok(true, "Successfully declined updating old contact!"); next(); };
  },
  function () {
    ok(true, "Retrieving a specific contact by ID");
    var options = {filterBy: ["id"],
                   filterOp: "equals",
                   filterValue: sample_id1};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 1, "Found exactly 1 contact.");
      findResult1 = req.result[0];
      ok(findResult1.id == sample_id1, "Same ID");
      checkContacts(findResult1, properties1);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving a specific contact by givenName");
    var options = {filterBy: ["givenName"],
                   filterOp: "equals",
                   filterValue: properties1.givenName[0]};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 1, "Found exactly 1 contact.");
      findResult1 = req.result[0];
      ok(findResult1.id == sample_id1, "Same ID");
      checkContacts(findResult1, properties1);
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Modifying contact2");
    findResult1.impp = properties1.impp = [{value: "phil impp"}];
    req = mozContacts.save(findResult1);
    req.onsuccess = function () {
      var req2 = mozContacts.find({});
      req2.onsuccess = function () {
        ok(req2.result.length == 1, "Found exactly 1 contact.");
        findResult1 = req2.result[0];
        ok(findResult1.id == sample_id1, "Same ID");
        checkContacts(findResult1, properties1);
        ok(findResult1.impp.length == 1, "Found exactly 1 IMS info.");
        next();
      }
      req2.onerror = onFailure;
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Searching contacts by query");
    var options = {filterBy: ["name", "email"],
                   filterOp: "contains",
                   filterValue: properties1.name[0].substring(0,4)};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 1, "Found exactly 1 contact.");
      findResult1 = req.result[0];
      ok(findResult1.id == sample_id1, "Same ID");
      checkContacts(findResult1, properties1);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Searching contacts by query");
    var options = {filterBy: ["nickname", "email"],
                   filterOp: "contains",
                   filterValue: properties1.nickname};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 1, "Found exactly 1 contact.");
      findResult1 = req.result[0];
      ok(findResult1.id == sample_id1, "Same ID");
      checkContacts(findResult1, properties1);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Searching contacts with multiple indices");
    var options = {filterBy: ["nickname", "email", "name"],
                   filterOp: "equals",
                   filterValue: properties1.nickname};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 1, "Found exactly 1 contact.");
      findResult1 = req.result[0];
      ok(findResult1.id == sample_id1, "Same ID");
      checkContacts(findResult1, properties1);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Modifying contact3");
    findResult1.email = [{value: properties1.nickname}];
    findResult1.nickname = "TEST";
    var newContact = new mozContact();
    newContact.init(findResult1);
    req = mozContacts.save(newContact);
    req.onsuccess = function () {
      var options = {filterBy: ["nickname", "email", "name"],
                     filterOp: "contains",
                     filterValue: properties1.nickname};
      // One contact has it in nickname and the other in email
      var req2 = mozContacts.find(options);
      req2.onsuccess = function () {
        ok(req2.result.length == 2, "Found exactly 2 contacts.");
        ok(req2.result[0].id != req2.result[1].id, "Different ID");
        next();
      }
      req2.onerror = onFailure;
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Deleting contact" + findResult1.id);
    req = mozContacts.remove(findResult1);
    req.onsuccess = function () {
      var req2 = mozContacts.find({});
      req2.onsuccess = function () {
        ok(req2.result.length == 1, "One contact left.");
        findResult1 = req2.result[0];
        next();
      }
      req2.onerror = onFailure;
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Deleting database");
    req = mozContacts.remove(findResult1);
    req.onsuccess =  function () {
      clearTemps();
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Adding a new contact");
    createResult1 = new mozContact();
    createResult1.init(properties1);
    req = mozContacts.save(createResult1)
    req.onsuccess = function () {
      ok(createResult1.id, "The contact now has an ID.");
      sample_id1 = createResult1.id;
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Adding a new contact2");
    createResult2 = new mozContact();
    createResult2.init(properties2);
    req = mozContacts.save(createResult2);
    req.onsuccess = function () {
      ok(createResult2.id, "The contact now has an ID.");
      sample_id2 = createResult2.id;
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving all contacts");
    req = mozContacts.find({})
    req.onsuccess = function () {
      ok(req.result.length == 2, "Found exactly 2 contact.");
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    console.log("Searching contacts by query1");
    var options = {filterBy: ["name", "email"],
                   filterOp: "contains",
                   filterValue: properties1.name[0].substring(0, 4)}
    req = mozContacts.find(options)
    req.onsuccess = function () {
      ok(req.result.length == 1, "Found exactly 1 contact.");
      findResult1 = req.result[0];
      ok(findResult1.id == sample_id1, "Same ID");
      checkContacts(findResult1, createResult1);
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Searching contacts by query2");
    var options = {filterBy: ["name", "email"],
                   filterOp: "contains",
                   filterValue: properties2.name[0].substring(0, 4)};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 1, "Found exactly 1 contact.");
      findResult1 = req.result[0];
      ok(findResult1.adr.length == 2, "Adr length 2");
      checkContacts(findResult1, createResult2);
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Searching contacts by tel");
    var options = {filterBy: ["tel"],
                   filterOp: "contains",
                   filterValue: properties2.tel[0].value.substring(0, 7)};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 1, "Found exactly 1 contact.");
      findResult1 = req.result[0];
      ok(findResult1.id == sample_id2, "Same ID");
      checkContacts(findResult1, createResult2);
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Searching contacts by email");
    var options = {filterBy: ["email"],
                   filterOp: "contains",
                   filterValue: properties2.email[0].value.substring(0, 4)};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 1, "Found exactly 1 contact.");
      findResult1 = req.result[0];
      ok(findResult1.id == sample_id2, "Same ID");
      checkContacts(findResult1, createResult2);
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Deleting database");
    req = mozContacts.clear();
    req.onsuccess = function () {
      clearTemps();
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Adding 100 contacts");
    for (var i=0; i<99; i++) {
      createResult1 = new mozContact();
      createResult1.init(properties1);
      req = mozContacts.save(createResult1);
      req.onsuccess = function () {
        ok(createResult1.id, "The contact now has an ID.");
      };
      req.onerror = onFailure;
    };
    createResult1 = new mozContact();
    createResult1.init(properties1);
    req = mozContacts.save(createResult1);
    req.onsuccess = function () {
      ok(createResult1.id, "The contact now has an ID.");
      ok(createResult1.name == properties1.name, "Same Name");
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving all contacts");
    req = mozContacts.find({});
    req.onsuccess = function () {
      ok(req.result.length == 100, "100 Entries.");
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving all contacts with limit 10");
    var options = { filterLimit: 10 };
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 10, "10 Entries.");
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving all contacts with limit 10 and sorted");
    var options = { filterLimit: 10,
                    sortBy: 'FamilyName',
                    sortOrder: 'descending' };
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 10, "10 Entries.");
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving all contacts2");
    var options = {filterBy: ["name"],
                   filterOp: "contains",
                   filterValue: properties1.name[0].substring(0, 4)};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 100, "100 Entries.");
      checkContacts(createResult1, req.result[99]);
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving all contacts3");
    var options = {filterBy: ["name", "givenName", "tel", "email", "note"],
                   filterOp: "contains",
                   filterValue: properties1.name[0].substring(0, 4),
                   filterLimit: 15 };
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 15, "15 Entries.");
      checkContacts(createResult1, req.result[10]);
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Deleting database");
    req = mozContacts.clear();
    req.onsuccess = function () {
      clearTemps();
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Testing clone contact");
    createResult1 = new mozContact();
    createResult1.init(properties1);
    req = mozContacts.save(createResult1);
    req.onsuccess = function () {
      ok(createResult1.id, "The contact now has an ID.");
      ok(createResult1.name == properties1.name, "Same Name");
      next();
    }
    req.onerror = onFailure;
  },
  function() {
    ok(true, "Testing clone contact2");
    var cloned = new mozContact(createResult1);
    ok(cloned.id != createResult1.id, "Cloned contact has new ID");
    cloned.email = {value: "new email!"};
    cloned.givenName = "Tom";
    req = mozContacts.save(cloned);
    req.onsuccess = function () {
      ok(cloned.id, "The contact now has an ID.");
      ok(cloned.email.value == "new email!", "Same Email");
      ok(createResult1.email != cloned.email, "Clone has different email");
      ok(cloned.givenName == "Tom", "New Name");
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Retrieving all contacts");
    var options = {filterBy: ["name"],
                   filterOp: "contains",
                   filterValue: properties2.name[0].substring(0, 4)};
    req = mozContacts.find({});
    req.onsuccess = function () {
      ok(req.result.length == 2, "2 Entries.");
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Search with redundant fields should only return 1 contact");
    createResult1 = new mozContact();
    createResult1.init({name: "XXX", nickname: "XXX", email: [{value: "XXX"}], tel: {value: "XXX"}});
    req = mozContacts.save(createResult1);
    req.onsuccess = function() {
      var options = {filterBy: [],
                     filterOp: "equals",
                     filterValue: "XXX"};
      var req2 = mozContacts.find(options);
      req2.onsuccess = function() {
        ok(req2.result.length == 1, "1 Entry");
        next();
      }
      req2.onerror = onFailure;
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Deleting database");
    req = mozContacts.clear()
    req.onsuccess = function () {
      ok(true, "Deleted the database");
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Test sorting");
    createResult1 = new mozContact();
    createResult1.init(c3);
    req = navigator.mozContacts.save(createResult1);
    req.onsuccess = function () {
      ok(createResult1.id, "The contact now has an ID.");
      checkContacts(c3, createResult1);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Test sorting");
    createResult1 = new mozContact();
    createResult1.init(c2);
    req = navigator.mozContacts.save(createResult1);
    req.onsuccess = function () {
      ok(createResult1.id, "The contact now has an ID.");
      checkContacts(c2, createResult1);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Test sorting");
    createResult1 = new mozContact();
    createResult1.init(c4);
    req = navigator.mozContacts.save(createResult1);
    req.onsuccess = function () {
      ok(createResult1.id, "The contact now has an ID.");
      checkContacts(c4, createResult1);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Test sorting");
    createResult1 = new mozContact();
    createResult1.init(c1);
    req = navigator.mozContacts.save(createResult1);
    req.onsuccess = function () {
      ok(createResult1.id, "The contact now has an ID.");
      checkContacts(c1, createResult1);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Test sorting");
    var options = {sortBy: "familyName",
                   sortOrder: "ascending"};
    req = navigator.mozContacts.find(options);
    req.onsuccess = function () {
      is(req.result.length, 4, "4 results");
      checkContacts(req.result[0], c1);
      checkContacts(req.result[1], c2);
      checkContacts(req.result[2], c3);
      checkContacts(req.result[3], c4);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Test sorting");
    var options = {sortBy: "familyName",
                   sortOrder: "descending"};
    req = navigator.mozContacts.find(options);
    req.onsuccess = function () {
      is(req.result.length, 4, "4 results");
      checkContacts(req.result[0], c4);
      checkContacts(req.result[1], c3);
      checkContacts(req.result[2], c2);
      checkContacts(req.result[3], c1);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Test sorting");
    createResult1 = new mozContact();
    createResult1.init(c5);
    req = navigator.mozContacts.save(createResult1);
    req.onsuccess = function () {
      ok(createResult1.id, "The contact now has an ID.");
      checkContacts(c5, createResult1);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Test sorting with empty string");
    var options = {sortBy: "familyName",
                   sortOrder: "ascending"};
    req = navigator.mozContacts.find(options);
    req.onsuccess = function () {
      is(req.result.length, 5, "5 results");
      checkContacts(req.result[0], c5);
      checkContacts(req.result[1], c1);
      checkContacts(req.result[2], c2);
      checkContacts(req.result[3], c3);
      checkContacts(req.result[4], c4);
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Don't allow to add custom fields");
    createResult1 = new mozContact();
    createResult1.init({name: "customTest", yyy: "XXX"});
    req = mozContacts.save(createResult1);
    req.onsuccess = function() {
      var options = {filterBy: [],
                     filterOp: "equals",
                     filterValue: "customTest"};
      var req2 = mozContacts.find(options);
      req2.onsuccess = function() {
        ok(req2.result.length == 1, "1 Entry");
        checkStr(req2.result.name, "customTest", "same name");
        ok(req2.result.yyy === undefined, "custom property undefined");
        next();
      }
      req2.onerror = onFailure;
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Deleting database");
    req = mozContacts.clear()
    req.onsuccess = function () {
      ok(true, "Deleted the database");
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Adding a new contact with properties2");
    createResult2 = new mozContact();
    createResult2.init(properties2);
    req = mozContacts.save(createResult2);
    req.onsuccess = function () {
      ok(createResult2.id, "The contact now has an ID.");
      sample_id2 = createResult2.id;
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Test category search with contains");
    var options = {filterBy: ["category"],
                   filterOp: "contains",
                   filterValue: properties2.category[0]};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 1, "1 Entry.");
      checkContacts(req.result[0], createResult2);
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Test category search with equals");
    var options = {filterBy: ["category"],
                   filterOp: "equals",
                   filterValue: properties2.category[0]};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 1, "1 Entry.");
      checkContacts(req.result[0], createResult2);
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Deleting database");
    req = mozContacts.clear()
    req.onsuccess = function () {
      ok(true, "Deleted the database");
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Adding empty contact");
    createResult1 = new mozContact();
    createResult1.init({givenName: 5});
    req = navigator.mozContacts.save(createResult1);
    req.onsuccess = function () {
      ok(createResult1.id, "The contact now has an ID.");
      sample_id1 = createResult1.id;
      next();
    };
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Test category search with equals");
    var options = {filterBy: ["givenName"],
                   filterOp: "contains",
                   filterValue: 5};
    req = mozContacts.find(options);
    req.onsuccess = function () {
      ok(req.result.length == 1, "1 Entry.");
      checkContacts(req.result[0], createResult1);
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "Deleting database");
    req = mozContacts.clear()
    req.onsuccess = function () {
      ok(true, "Deleted the database");
      next();
    }
    req.onerror = onFailure;
  },
  function () {
    ok(true, "all done!\n");
    clearTemps();

    SimpleTest.finish();
  }
];

function next() {
  ok(true, "Begin!");
  if (index >= steps.length) {
    ok(false, "Shouldn't get here!");
    return;
  }
  try {
    steps[index]();
  } catch(ex) {
    ok(false, "Caught exception", ex);
  }
  index += 1;
}

function permissionTest() {
  if (gContactsEnabled) {
    next();
  } else {
    is(mozContacts, null, "mozContacts is null when not enabled.");
    SimpleTest.finish();
  }
}

var gContactsEnabled = SpecialPowers.getBoolPref("dom.mozContacts.enabled");
SimpleTest.waitForExplicitFinish();
addLoadEvent(permissionTest);

ok(true, "test passed");
</script>
</pre>
</body>
</html>