summaryrefslogtreecommitdiffstats
path: root/services/sync/tests/tps
diff options
context:
space:
mode:
Diffstat (limited to 'services/sync/tests/tps')
-rw-r--r--services/sync/tests/tps/.eslintrc.js28
-rw-r--r--services/sync/tests/tps/addons/api/restartless-xpi@tests.mozilla.org.json21
-rw-r--r--services/sync/tests/tps/addons/api/test-webext@quality.mozilla.org.json21
-rw-r--r--services/sync/tests/tps/addons/restartless.xpibin0 -> 485 bytes
-rw-r--r--services/sync/tests/tps/addons/webextension.xpibin0 -> 3412 bytes
-rw-r--r--services/sync/tests/tps/all_tests.json34
-rw-r--r--services/sync/tests/tps/test_addon_reconciling.js45
-rw-r--r--services/sync/tests/tps/test_addon_restartless_xpi.js64
-rw-r--r--services/sync/tests/tps/test_addon_webext_xpi.js65
-rw-r--r--services/sync/tests/tps/test_addon_wipe.js31
-rw-r--r--services/sync/tests/tps/test_addresses.js84
-rw-r--r--services/sync/tests/tps/test_bookmark_conflict.js138
-rw-r--r--services/sync/tests/tps/test_bookmarks_in_same_named_folder.js53
-rw-r--r--services/sync/tests/tps/test_bug501528.js75
-rw-r--r--services/sync/tests/tps/test_bug530717.js47
-rw-r--r--services/sync/tests/tps/test_bug531489.js43
-rw-r--r--services/sync/tests/tps/test_bug535326.js148
-rw-r--r--services/sync/tests/tps/test_bug538298.js78
-rw-r--r--services/sync/tests/tps/test_bug546807.js38
-rw-r--r--services/sync/tests/tps/test_bug556509.js32
-rw-r--r--services/sync/tests/tps/test_bug562515.js90
-rw-r--r--services/sync/tests/tps/test_bug575423.js67
-rw-r--r--services/sync/tests/tps/test_client_wipe.js142
-rw-r--r--services/sync/tests/tps/test_creditcards.js62
-rw-r--r--services/sync/tests/tps/test_existing_bookmarks.js80
-rw-r--r--services/sync/tests/tps/test_extstorage.js154
-rw-r--r--services/sync/tests/tps/test_formdata.js63
-rw-r--r--services/sync/tests/tps/test_history.js129
-rw-r--r--services/sync/tests/tps/test_history_collision.js98
-rw-r--r--services/sync/tests/tps/test_passwords.js119
-rw-r--r--services/sync/tests/tps/test_prefs.js35
-rw-r--r--services/sync/tests/tps/test_privbrw_passwords.js105
-rw-r--r--services/sync/tests/tps/test_privbrw_tabs.js86
-rw-r--r--services/sync/tests/tps/test_special_tabs.js63
-rw-r--r--services/sync/tests/tps/test_sync.js403
-rw-r--r--services/sync/tests/tps/test_tabs.js42
36 files changed, 2783 insertions, 0 deletions
diff --git a/services/sync/tests/tps/.eslintrc.js b/services/sync/tests/tps/.eslintrc.js
new file mode 100644
index 0000000000..182e87933b
--- /dev/null
+++ b/services/sync/tests/tps/.eslintrc.js
@@ -0,0 +1,28 @@
+"use strict";
+
+module.exports = {
+ globals: {
+ // Injected into tests via tps.jsm
+ Addons: false,
+ Addresses: false,
+ Bookmarks: false,
+ CreditCards: false,
+ EnableEngines: false,
+ EnsureTracking: false,
+ ExtStorage: false,
+ Formdata: false,
+ History: false,
+ Login: false,
+ Passwords: false,
+ Phase: false,
+ Prefs: false,
+ STATE_DISABLED: false,
+ STATE_ENABLED: false,
+ Sync: false,
+ SYNC_WIPE_CLIENT: false,
+ SYNC_WIPE_REMOTE: false,
+ Tabs: false,
+ Windows: false,
+ WipeServer: false,
+ },
+};
diff --git a/services/sync/tests/tps/addons/api/restartless-xpi@tests.mozilla.org.json b/services/sync/tests/tps/addons/api/restartless-xpi@tests.mozilla.org.json
new file mode 100644
index 0000000000..8593bad089
--- /dev/null
+++ b/services/sync/tests/tps/addons/api/restartless-xpi@tests.mozilla.org.json
@@ -0,0 +1,21 @@
+{
+ "next": null,
+ "results": [
+ {
+ "name": "Restartless Test XPI",
+ "type": "extension",
+ "guid": "restartless-xpi@tests.mozilla.org",
+ "current_version": {
+ "version": "1.0",
+ "files": [
+ {
+ "platform": "all",
+ "size": 485,
+ "url": "http://127.0.0.1:4567/addons/restartless.xpi"
+ }
+ ]
+ },
+ "last_updated": "2011-09-05T20:42:09Z"
+ }
+ ]
+}
diff --git a/services/sync/tests/tps/addons/api/test-webext@quality.mozilla.org.json b/services/sync/tests/tps/addons/api/test-webext@quality.mozilla.org.json
new file mode 100644
index 0000000000..298ecc2ead
--- /dev/null
+++ b/services/sync/tests/tps/addons/api/test-webext@quality.mozilla.org.json
@@ -0,0 +1,21 @@
+{
+ "next": null,
+ "results": [
+ {
+ "name": "Tet Webext XPI",
+ "type": "extension",
+ "guid": "test-webext@quality.mozilla.org",
+ "current_version": {
+ "version": "1.0",
+ "files": [
+ {
+ "platform": "all",
+ "size": 3412,
+ "url": "http://127.0.0.1:4567/addons/webextension.xpi"
+ }
+ ]
+ },
+ "last_updated": "2018-04-17T18:24:42Z"
+ }
+ ]
+}
diff --git a/services/sync/tests/tps/addons/restartless.xpi b/services/sync/tests/tps/addons/restartless.xpi
new file mode 100644
index 0000000000..973bc00cb5
--- /dev/null
+++ b/services/sync/tests/tps/addons/restartless.xpi
Binary files differ
diff --git a/services/sync/tests/tps/addons/webextension.xpi b/services/sync/tests/tps/addons/webextension.xpi
new file mode 100644
index 0000000000..0ed64f79ac
--- /dev/null
+++ b/services/sync/tests/tps/addons/webextension.xpi
Binary files differ
diff --git a/services/sync/tests/tps/all_tests.json b/services/sync/tests/tps/all_tests.json
new file mode 100644
index 0000000000..ea92e04b8f
--- /dev/null
+++ b/services/sync/tests/tps/all_tests.json
@@ -0,0 +1,34 @@
+{
+ "tests": {
+ "test_bookmark_conflict.js": {},
+ "test_sync.js": {},
+ "test_prefs.js": {},
+ "test_tabs.js": {},
+ "test_passwords.js": {},
+ "test_history.js": {},
+ "test_formdata.js": {},
+ "test_bug530717.js": {},
+ "test_bug531489.js": {},
+ "test_bug538298.js": {},
+ "test_bug556509.js": {},
+ "test_bug562515.js": {},
+ "test_bug535326.js": {},
+ "test_bug501528.js": {},
+ "test_bug575423.js": {},
+ "test_bug546807.js": {},
+ "test_history_collision.js": {},
+ "test_privbrw_passwords.js": {},
+ "test_privbrw_tabs.js": {},
+ "test_bookmarks_in_same_named_folder.js": {},
+ "test_client_wipe.js": {},
+ "test_special_tabs.js": {},
+ "test_addon_restartless_xpi.js": { "disabled": "Bug 1498974" },
+ "test_addon_webext_xpi.js": { "disabled": "Bug 1498974" },
+ "test_addon_reconciling.js": { "disabled": "Bug 1498974" },
+ "test_addon_wipe.js": { "disabled": "Bug 1498974" },
+ "test_existing_bookmarks.js": {},
+ "test_addresses.js": {},
+ "test_creditcards.js": {},
+ "test_extstorage.js": {}
+ }
+}
diff --git a/services/sync/tests/tps/test_addon_reconciling.js b/services/sync/tests/tps/test_addon_reconciling.js
new file mode 100644
index 0000000000..9c928734c8
--- /dev/null
+++ b/services/sync/tests/tps/test_addon_reconciling.js
@@ -0,0 +1,45 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// This test verifies that record reconciling works as expected. It makes
+// similar changes to add-ons in separate profiles and does a sync to verify
+// the proper action is taken.
+EnableEngines(["addons"]);
+
+var phases = {
+ phase01: "profile1",
+ phase02: "profile2",
+ phase03: "profile1",
+ phase04: "profile2",
+ phase05: "profile1",
+ phase06: "profile2",
+};
+
+const id = "restartless-xpi@tests.mozilla.org";
+
+// Install the add-on in 2 profiles.
+Phase("phase01", [
+ [Addons.verifyNot, [id]],
+ [Addons.install, [id]],
+ [Addons.verify, [id], STATE_ENABLED],
+ [Sync],
+]);
+Phase("phase02", [
+ [Addons.verifyNot, [id]],
+ [Sync],
+ [Addons.verify, [id], STATE_ENABLED],
+]);
+
+// Now we disable in one and uninstall in the other.
+Phase("phase03", [
+ [Sync], // Get GUID updates, potentially.
+ [Addons.setEnabled, [id], STATE_DISABLED],
+ // We've changed the state, but don't want this profile to sync until phase5,
+ // so if we ran a validation now we'd be expecting to find errors.
+ [Addons.skipValidation],
+]);
+Phase("phase04", [[EnsureTracking], [Addons.uninstall, [id]], [Sync]]);
+
+// When we sync, the uninstall should take precedence because it was newer.
+Phase("phase05", [[Sync]]);
+Phase("phase06", [[Sync], [Addons.verifyNot, [id]]]);
diff --git a/services/sync/tests/tps/test_addon_restartless_xpi.js b/services/sync/tests/tps/test_addon_restartless_xpi.js
new file mode 100644
index 0000000000..2b14245a6e
--- /dev/null
+++ b/services/sync/tests/tps/test_addon_restartless_xpi.js
@@ -0,0 +1,64 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// This test verifies that install of restartless extensions syncs to
+// other profiles.
+EnableEngines(["addons"]);
+
+var phases = {
+ phase01: "profile1",
+ phase02: "profile2",
+ phase03: "profile1",
+ phase04: "profile2",
+ phase05: "profile1",
+ phase06: "profile2",
+ phase07: "profile1",
+ phase08: "profile2",
+};
+
+const id = "restartless-xpi@tests.mozilla.org";
+
+// Verify install is synced
+Phase("phase01", [
+ [Addons.verifyNot, [id]],
+ [Addons.install, [id]],
+ [Addons.verify, [id], STATE_ENABLED],
+ [Sync],
+]);
+Phase("phase02", [
+ [Addons.verifyNot, [id]],
+ [Sync],
+ [Addons.verify, [id], STATE_ENABLED],
+]);
+
+// Now disable and see that is is synced.
+Phase("phase03", [
+ [EnsureTracking],
+ [Addons.setEnabled, [id], STATE_DISABLED],
+ [Addons.verify, [id], STATE_DISABLED],
+ [Sync],
+]);
+Phase("phase04", [[Sync], [Addons.verify, [id], STATE_DISABLED]]);
+
+// Enable and see it is synced.
+Phase("phase05", [
+ [EnsureTracking],
+ [Addons.setEnabled, [id], STATE_ENABLED],
+ [Addons.verify, [id], STATE_ENABLED],
+ [Sync],
+]);
+Phase("phase06", [[Sync], [Addons.verify, [id], STATE_ENABLED]]);
+
+// Uninstall and see it is synced.
+Phase("phase07", [
+ [EnsureTracking],
+ [Addons.verify, [id], STATE_ENABLED],
+ [Addons.uninstall, [id]],
+ [Addons.verifyNot, [id]],
+ [Sync],
+]);
+Phase("phase08", [
+ [Addons.verify, [id], STATE_ENABLED],
+ [Sync],
+ [Addons.verifyNot, [id]],
+]);
diff --git a/services/sync/tests/tps/test_addon_webext_xpi.js b/services/sync/tests/tps/test_addon_webext_xpi.js
new file mode 100644
index 0000000000..27065ee6af
--- /dev/null
+++ b/services/sync/tests/tps/test_addon_webext_xpi.js
@@ -0,0 +1,65 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// This test verifies that install of web extensions sync to other profiles.
+// It's more or less copied from test_addon_restartless_xpi with a different id.
+
+EnableEngines(["addons"]);
+
+var phases = {
+ phase01: "profile1",
+ phase02: "profile2",
+ phase03: "profile1",
+ phase04: "profile2",
+ phase05: "profile1",
+ phase06: "profile2",
+ phase07: "profile1",
+ phase08: "profile2",
+};
+
+const id = "test-webext@quality.mozilla.org";
+
+// Verify install is synced
+Phase("phase01", [
+ [Addons.verifyNot, [id]],
+ [Addons.install, [id]],
+ [Addons.verify, [id], STATE_ENABLED],
+ [Sync],
+]);
+Phase("phase02", [
+ [Addons.verifyNot, [id]],
+ [Sync],
+ [Addons.verify, [id], STATE_ENABLED],
+]);
+
+// Now disable and see that is is synced.
+Phase("phase03", [
+ [EnsureTracking],
+ [Addons.setEnabled, [id], STATE_DISABLED],
+ [Addons.verify, [id], STATE_DISABLED],
+ [Sync],
+]);
+Phase("phase04", [[Sync], [Addons.verify, [id], STATE_DISABLED]]);
+
+// Enable and see it is synced.
+Phase("phase05", [
+ [EnsureTracking],
+ [Addons.setEnabled, [id], STATE_ENABLED],
+ [Addons.verify, [id], STATE_ENABLED],
+ [Sync],
+]);
+Phase("phase06", [[Sync], [Addons.verify, [id], STATE_ENABLED]]);
+
+// Uninstall and see it is synced.
+Phase("phase07", [
+ [EnsureTracking],
+ [Addons.verify, [id], STATE_ENABLED],
+ [Addons.uninstall, [id]],
+ [Addons.verifyNot, [id]],
+ [Sync],
+]);
+Phase("phase08", [
+ [Addons.verify, [id], STATE_ENABLED],
+ [Sync],
+ [Addons.verifyNot, [id]],
+]);
diff --git a/services/sync/tests/tps/test_addon_wipe.js b/services/sync/tests/tps/test_addon_wipe.js
new file mode 100644
index 0000000000..038f01d014
--- /dev/null
+++ b/services/sync/tests/tps/test_addon_wipe.js
@@ -0,0 +1,31 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// This test ensures that a client wipe followed by an "initial" sync will
+// restore add-ons. This test should expose flaws in the reconciling logic,
+// specifically around AddonsReconciler. This test is in response to bug
+// 792990.
+
+EnableEngines(["addons"]);
+
+var phases = {
+ phase01: "profile1",
+ phase02: "profile1",
+ phase03: "profile1",
+};
+
+const id1 = "restartless-xpi@tests.mozilla.org";
+const id2 = "test-webext@quality.mozilla.org";
+
+Phase("phase01", [[Addons.install, [id1]], [Addons.install, [id2]], [Sync]]);
+Phase("phase02", [
+ [Addons.verify, [id1], STATE_ENABLED],
+ [Addons.verify, [id2], STATE_ENABLED],
+ [Sync, SYNC_WIPE_CLIENT],
+ [Sync],
+]);
+Phase("phase03", [
+ [Addons.verify, [id1], STATE_ENABLED],
+ [Addons.verify, [id2], STATE_ENABLED],
+ [Sync], // Sync to ensure that the addon validator can run without error
+]);
diff --git a/services/sync/tests/tps/test_addresses.js b/services/sync/tests/tps/test_addresses.js
new file mode 100644
index 0000000000..33af349dd5
--- /dev/null
+++ b/services/sync/tests/tps/test_addresses.js
@@ -0,0 +1,84 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/* global Services */
+Services.prefs.setBoolPref("services.sync.engine.addresses", true);
+
+EnableEngines(["addresses"]);
+
+var phases = {
+ phase1: "profile1",
+ phase2: "profile2",
+ phase3: "profile1",
+};
+
+const address1 = [
+ {
+ "given-name": "Timothy",
+ "additional-name": "John",
+ "family-name": "Berners-Lee",
+ organization: "World Wide Web Consortium",
+ "street-address": "32 Vassar Street\nMIT Room 32-G524",
+ "address-level2": "Cambridge",
+ "address-level1": "MA",
+ "postal-code": "02139",
+ country: "US",
+ tel: "+16172535702",
+ email: "timbl@w3.org",
+ changes: {
+ organization: "W3C",
+ },
+ "unknown-1": "an unknown field from another client",
+ },
+];
+
+const address1_after = [
+ {
+ "given-name": "Timothy",
+ "additional-name": "John",
+ "family-name": "Berners-Lee",
+ organization: "W3C",
+ "street-address": "32 Vassar Street\nMIT Room 32-G524",
+ "address-level2": "Cambridge",
+ "address-level1": "MA",
+ "postal-code": "02139",
+ country: "US",
+ tel: "+16172535702",
+ email: "timbl@w3.org",
+ "unknown-1": "an unknown field from another client",
+ },
+];
+
+const address2 = [
+ {
+ "given-name": "John",
+ "additional-name": "R.",
+ "family-name": "Smith",
+ organization: "Mozilla",
+ "street-address":
+ "Geb\u00E4ude 3, 4. Obergeschoss\nSchlesische Stra\u00DFe 27",
+ "address-level2": "Berlin",
+ "address-level1": "BE",
+ "postal-code": "10997",
+ country: "DE",
+ tel: "+4930983333000",
+ email: "timbl@w3.org",
+ },
+];
+
+Phase("phase1", [[Addresses.add, address1], [Sync]]);
+
+Phase("phase2", [
+ [Sync],
+ [Addresses.verify, address1],
+ [Addresses.modify, address1],
+ [Addresses.add, address2],
+ [Sync],
+]);
+
+Phase("phase3", [
+ [Sync],
+ [Addresses.verify, address1_after],
+ [Addresses.verify, address2],
+ [Sync],
+]);
diff --git a/services/sync/tests/tps/test_bookmark_conflict.js b/services/sync/tests/tps/test_bookmark_conflict.js
new file mode 100644
index 0000000000..2832bded5d
--- /dev/null
+++ b/services/sync/tests/tps/test_bookmark_conflict.js
@@ -0,0 +1,138 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+EnableEngines(["bookmarks"]);
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in JSON format as it will get parsed by the Python
+ * testrunner. It is parsed by the YAML package, so it relatively flexible.
+ */
+var phases = {
+ phase1: "profile1",
+ phase2: "profile2",
+ phase3: "profile1",
+ phase4: "profile2",
+};
+
+// the initial list of bookmarks to add to the browser
+var bookmarksInitial = {
+ menu: [
+ { folder: "foldera" },
+ { folder: "folderb" },
+ { folder: "folderc" },
+ { folder: "folderd" },
+ ],
+
+ "menu/foldera": [{ uri: "http://www.cnn.com", title: "CNN" }],
+ "menu/folderb": [{ uri: "http://www.apple.com", title: "Apple", tags: [] }],
+ "menu/folderc": [{ uri: "http://www.yahoo.com", title: "Yahoo" }],
+
+ "menu/folderd": [],
+};
+
+// a list of bookmarks to delete during a 'delete' action on P2
+var bookmarksToDelete = {
+ menu: [{ folder: "foldera" }, { folder: "folderb" }],
+ "menu/folderc": [{ uri: "http://www.yahoo.com", title: "Yahoo" }],
+};
+
+// the modifications to make on P1, after P2 has synced, but before P1 has gotten
+// P2's changes
+var bookmarkMods = {
+ menu: [
+ { folder: "foldera" },
+ { folder: "folderb" },
+ { folder: "folderc" },
+ { folder: "folderd" },
+ ],
+
+ // we move this child out of its folder (p1), after deleting the folder (p2)
+ // and expect the child to come back to p2 after sync.
+ "menu/foldera": [
+ {
+ uri: "http://www.cnn.com",
+ title: "CNN",
+ changes: { location: "menu/folderd" },
+ },
+ ],
+
+ // we rename this child (p1) after deleting the folder (p2), and expect the child
+ // to be moved into great grandparent (menu)
+ "menu/folderb": [
+ {
+ uri: "http://www.apple.com",
+ title: "Apple",
+ tags: [],
+ changes: { title: "Mac" },
+ },
+ ],
+
+ // we move this child (p1) after deleting the child (p2) and expect it to survive
+ "menu/folderc": [
+ {
+ uri: "http://www.yahoo.com",
+ title: "Yahoo",
+ changes: { location: "menu/folderd" },
+ },
+ ],
+
+ "menu/folderd": [],
+};
+
+// a list of bookmarks to delete during a 'delete' action
+bookmarksToDelete = {
+ menu: [{ folder: "foldera" }, { folder: "folderb" }],
+ "menu/folderc": [{ uri: "http://www.yahoo.com", title: "Yahoo" }],
+};
+
+// expected bookmark state after conflict resolution
+var bookmarksExpected = {
+ menu: [
+ { folder: "folderc" },
+ { folder: "folderd" },
+ { uri: "http://www.apple.com", title: "Mac" },
+ ],
+
+ "menu/folderc": [],
+
+ "menu/folderd": [
+ { uri: "http://www.cnn.com", title: "CNN" },
+ { uri: "http://www.yahoo.com", title: "Yahoo" },
+ ],
+};
+
+// Add bookmarks to profile1 and sync.
+Phase("phase1", [
+ [Bookmarks.add, bookmarksInitial],
+ [Bookmarks.verify, bookmarksInitial],
+ [Sync],
+ [Bookmarks.verify, bookmarksInitial],
+]);
+
+// Sync to profile2 and verify that the bookmarks are present. Delete
+// bookmarks/folders, verify that it's not present, and sync
+Phase("phase2", [
+ [Sync],
+ [Bookmarks.verify, bookmarksInitial],
+ [Bookmarks.delete, bookmarksToDelete],
+ [Bookmarks.verifyNot, bookmarksToDelete],
+ [Sync],
+]);
+
+// Using profile1, modify the bookmarks, and sync *after* the modification,
+// and then sync again to propagate the reconciliation changes.
+Phase("phase3", [
+ [Bookmarks.verify, bookmarksInitial],
+ [Bookmarks.modify, bookmarkMods],
+ [Sync],
+ [Bookmarks.verify, bookmarksExpected],
+ [Bookmarks.verifyNot, bookmarksToDelete],
+]);
+
+// Back in profile2, do a sync and verify that we're in the expected state
+Phase("phase4", [
+ [Sync],
+ [Bookmarks.verify, bookmarksExpected],
+ [Bookmarks.verifyNot, bookmarksToDelete],
+]);
diff --git a/services/sync/tests/tps/test_bookmarks_in_same_named_folder.js b/services/sync/tests/tps/test_bookmarks_in_same_named_folder.js
new file mode 100644
index 0000000000..69dd8ba8a6
--- /dev/null
+++ b/services/sync/tests/tps/test_bookmarks_in_same_named_folder.js
@@ -0,0 +1,53 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// bug 558077
+
+EnableEngines(["bookmarks"]);
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in JSON format as it will get parsed by the Python
+ * testrunner. It is parsed by the YAML package, so it relatively flexible.
+ */
+var phases = { phase1: "profile1", phase2: "profile2", phase3: "profile1" };
+
+var bookmarks_initial_1 = {
+ menu: [
+ { folder: "aaa", description: "foo" },
+ { uri: "http://www.mozilla.com" },
+ ],
+ "menu/aaa": [
+ { uri: "http://www.yahoo.com", title: "testing Yahoo" },
+ { uri: "http://www.google.com", title: "testing Google" },
+ ],
+};
+
+var bookmarks_initial_2 = {
+ menu: [
+ { folder: "aaa", description: "bar" },
+ { uri: "http://www.mozilla.com" },
+ ],
+ "menu/aaa": [
+ {
+ uri: "http://bugzilla.mozilla.org/show_bug.cgi?id=%s",
+ title: "Bugzilla",
+ },
+ { uri: "http://www.apple.com", tags: ["apple"] },
+ ],
+};
+
+Phase("phase1", [[Bookmarks.add, bookmarks_initial_1], [Sync]]);
+
+Phase("phase2", [
+ [Sync],
+ [Bookmarks.verify, bookmarks_initial_1],
+ [Bookmarks.add, bookmarks_initial_2],
+ [Sync],
+]);
+
+Phase("phase3", [
+ [Sync],
+ // XXX [Bookmarks.verify, bookmarks_initial_1],
+ [Bookmarks.verify, bookmarks_initial_2],
+]);
diff --git a/services/sync/tests/tps/test_bug501528.js b/services/sync/tests/tps/test_bug501528.js
new file mode 100644
index 0000000000..f86ba02403
--- /dev/null
+++ b/services/sync/tests/tps/test_bug501528.js
@@ -0,0 +1,75 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+EnableEngines(["passwords"]);
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in JSON format as it will get parsed by the Python
+ * testrunner. It is parsed by the YAML package, so it relatively flexible.
+ */
+var phases = {
+ phase1: "profile1",
+ phase2: "profile2",
+ phase3: "profile1",
+ phase4: "profile2",
+};
+
+/*
+ * Password lists
+ */
+
+var passwords_initial = [
+ {
+ hostname: "http://www.example.com",
+ submitURL: "http://login.example.com",
+ username: "joe",
+ password: "secret",
+ usernameField: "uname",
+ passwordField: "pword",
+ changes: {
+ password: "SeCrEt$$$",
+ },
+ },
+ {
+ hostname: "http://www.example.com",
+ realm: "login",
+ username: "jack",
+ password: "secretlogin",
+ },
+];
+
+var passwords_after_first_update = [
+ {
+ hostname: "http://www.example.com",
+ submitURL: "http://login.example.com",
+ username: "joe",
+ password: "SeCrEt$$$",
+ usernameField: "uname",
+ passwordField: "pword",
+ },
+ {
+ hostname: "http://www.example.com",
+ realm: "login",
+ username: "jack",
+ password: "secretlogin",
+ },
+];
+
+/*
+ * Test phases
+ */
+
+Phase("phase1", [[Passwords.add, passwords_initial], [Sync]]);
+
+Phase("phase2", [[Passwords.add, passwords_initial], [Sync]]);
+
+Phase("phase3", [
+ [Sync],
+ [Passwords.verify, passwords_initial],
+ [Passwords.modify, passwords_initial],
+ [Passwords.verify, passwords_after_first_update],
+ [Sync],
+]);
+
+Phase("phase4", [[Sync], [Passwords.verify, passwords_after_first_update]]);
diff --git a/services/sync/tests/tps/test_bug530717.js b/services/sync/tests/tps/test_bug530717.js
new file mode 100644
index 0000000000..37e6711cb5
--- /dev/null
+++ b/services/sync/tests/tps/test_bug530717.js
@@ -0,0 +1,47 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+EnableEngines(["prefs"]);
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in JSON format as it will get parsed by the Python
+ * testrunner. It is parsed by the YAML package, so it relatively flexible.
+ */
+var phases = { phase1: "profile1", phase2: "profile2", phase3: "profile1" };
+
+/*
+ * Preference lists
+ */
+
+var prefs1 = [
+ { name: "browser.startup.homepage", value: "http://www.getfirefox.com" },
+ { name: "browser.urlbar.maxRichResults", value: 20 },
+ { name: "privacy.clearOnShutdown.siteSettings", value: true },
+];
+
+var prefs2 = [
+ { name: "browser.startup.homepage", value: "http://www.mozilla.com" },
+ { name: "browser.urlbar.maxRichResults", value: 18 },
+ { name: "privacy.clearOnShutdown.siteSettings", value: false },
+];
+
+/*
+ * Test phases
+ */
+
+// Add prefs to profile1 and sync.
+Phase("phase1", [[Prefs.modify, prefs1], [Prefs.verify, prefs1], [Sync]]);
+
+// Sync profile2 and verify same prefs are present.
+Phase("phase2", [[Sync], [Prefs.verify, prefs1]]);
+
+// Using profile1, change some prefs, then do another sync with wipe-client.
+// Verify that the cloud's prefs are restored, and the recent local changes
+// discarded.
+Phase("phase3", [
+ [Prefs.modify, prefs2],
+ [Prefs.verify, prefs2],
+ [Sync, SYNC_WIPE_CLIENT],
+ [Prefs.verify, prefs1],
+]);
diff --git a/services/sync/tests/tps/test_bug531489.js b/services/sync/tests/tps/test_bug531489.js
new file mode 100644
index 0000000000..3cc79c87ec
--- /dev/null
+++ b/services/sync/tests/tps/test_bug531489.js
@@ -0,0 +1,43 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+EnableEngines(["bookmarks"]);
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in JSON format as it will get parsed by the Python
+ * testrunner. It is parsed by the YAML package, so it relatively flexible.
+ */
+var phases = { phase1: "profile1", phase2: "profile2", phase3: "profile1" };
+
+/*
+ * Bookmark asset lists: these define bookmarks that are used during the test
+ */
+
+// the initial list of bookmarks to add to the browser
+var bookmarks_initial = {
+ menu: [
+ { folder: "foldera" },
+ { uri: "http://www.google.com", title: "Google" },
+ ],
+ "menu/foldera": [{ uri: "http://www.google.com", title: "Google" }],
+ toolbar: [{ uri: "http://www.google.com", title: "Google" }],
+};
+
+/*
+ * Test phases
+ */
+
+// Add three bookmarks with the same url to different locations and sync.
+Phase("phase1", [
+ [Bookmarks.add, bookmarks_initial],
+ [Bookmarks.verify, bookmarks_initial],
+ [Sync],
+]);
+
+// Sync to profile2 and verify that all three bookmarks are present
+Phase("phase2", [[Sync], [Bookmarks.verify, bookmarks_initial]]);
+
+// Sync again to profile1 and verify that all three bookmarks are still
+// present.
+Phase("phase3", [[Sync], [Bookmarks.verify, bookmarks_initial]]);
diff --git a/services/sync/tests/tps/test_bug535326.js b/services/sync/tests/tps/test_bug535326.js
new file mode 100644
index 0000000000..ede8f45c10
--- /dev/null
+++ b/services/sync/tests/tps/test_bug535326.js
@@ -0,0 +1,148 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+EnableEngines(["tabs"]);
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in JSON format as it will get parsed by the Python
+ * testrunner. It is parsed by the YAML package, so it relatively flexible.
+ */
+var phases = { phase1: "profile1", phase2: "profile2" };
+
+var tabs1 = [
+ {
+ uri: "data:text/html,<html><head><title>Howdy</title></head><body>Howdy</body></html>",
+ title: "Howdy",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>America</title></head><body>America</body></html>",
+ title: "America",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Apple</title></head><body>Apple</body></html>",
+ title: "Apple",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>This</title></head><body>This</body></html>",
+ title: "This",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Bug</title></head><body>Bug</body></html>",
+ title: "Bug",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>IRC</title></head><body>IRC</body></html>",
+ title: "IRC",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Tinderbox</title></head><body>Tinderbox</body></html>",
+ title: "Tinderbox",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Fox</title></head><body>Fox</body></html>",
+ title: "Fox",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Hello</title></head><body>Hello</body></html>",
+ title: "Hello",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Eagle</title></head><body>Eagle</body></html>",
+ title: "Eagle",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Train</title></head><body>Train</body></html>",
+ title: "Train",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Macbook</title></head><body>Macbook</body></html>",
+ title: "Macbook",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Clock</title></head><body>Clock</body></html>",
+ title: "Clock",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Google</title></head><body>Google</body></html>",
+ title: "Google",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Human</title></head><body>Human</body></html>",
+ title: "Human",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Jetpack</title></head><body>Jetpack</body></html>",
+ title: "Jetpack",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Selenium</title></head><body>Selenium</body></html>",
+ title: "Selenium",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Mozilla</title></head><body>Mozilla</body></html>",
+ title: "Mozilla",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Firefox</title></head><body>Firefox</body></html>",
+ title: "Firefox",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Weave</title></head><body>Weave</body></html>",
+ title: "Weave",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Android</title></head><body>Android</body></html>",
+ title: "Android",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Bye</title></head><body>Bye</body></html>",
+ title: "Bye",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Hi</title></head><body>Hi</body></html>",
+ title: "Hi",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Final</title></head><body>Final</body></html>",
+ title: "Final",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Fennec</title></head><body>Fennec</body></html>",
+ title: "Fennec",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Mobile</title></head><body>Mobile</body></html>",
+ title: "Mobile",
+ profile: "profile1",
+ },
+];
+
+Phase("phase1", [[Tabs.add, tabs1], [Sync]]);
+
+Phase("phase2", [[Sync], [Tabs.verify, tabs1]]);
diff --git a/services/sync/tests/tps/test_bug538298.js b/services/sync/tests/tps/test_bug538298.js
new file mode 100644
index 0000000000..3f1abf2a96
--- /dev/null
+++ b/services/sync/tests/tps/test_bug538298.js
@@ -0,0 +1,78 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+EnableEngines(["bookmarks"]);
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in JSON format as it will get parsed by the Python
+ * testrunner. It is parsed by the YAML package, so it relatively flexible.
+ */
+var phases = {
+ phase1: "profile1",
+ phase2: "profile2",
+ phase3: "profile1",
+ phase4: "profile2",
+};
+
+/*
+ * Bookmark asset lists: these define bookmarks that are used during the test
+ */
+
+// the initial list of bookmarks to add to the browser
+var bookmarks_initial = {
+ toolbar: [
+ { uri: "http://www.google.com", title: "Google" },
+ {
+ uri: "http://www.cnn.com",
+ title: "CNN",
+ changes: {
+ position: "Google",
+ },
+ },
+ { uri: "http://www.mozilla.com", title: "Mozilla" },
+ {
+ uri: "http://www.firefox.com",
+ title: "Firefox",
+ changes: {
+ position: "Mozilla",
+ },
+ },
+ ],
+};
+
+var bookmarks_after_move = {
+ toolbar: [
+ { uri: "http://www.cnn.com", title: "CNN" },
+ { uri: "http://www.google.com", title: "Google" },
+ { uri: "http://www.firefox.com", title: "Firefox" },
+ { uri: "http://www.mozilla.com", title: "Mozilla" },
+ ],
+};
+
+/*
+ * Test phases
+ */
+
+// Add four bookmarks to the toolbar and sync.
+Phase("phase1", [
+ [Bookmarks.add, bookmarks_initial],
+ [Bookmarks.verify, bookmarks_initial],
+ [Sync],
+]);
+
+// Sync to profile2 and verify that all four bookmarks are present.
+Phase("phase2", [[Sync], [Bookmarks.verify, bookmarks_initial]]);
+
+// Change the order of the toolbar bookmarks, and sync.
+Phase("phase3", [
+ [Sync],
+ [Bookmarks.verify, bookmarks_initial],
+ [Bookmarks.modify, bookmarks_initial],
+ [Bookmarks.verify, bookmarks_after_move],
+ [Sync],
+]);
+
+// Go back to profile2, sync, and verify that the bookmarks are reordered
+// as expected.
+Phase("phase4", [[Sync], [Bookmarks.verify, bookmarks_after_move]]);
diff --git a/services/sync/tests/tps/test_bug546807.js b/services/sync/tests/tps/test_bug546807.js
new file mode 100644
index 0000000000..f02f632b41
--- /dev/null
+++ b/services/sync/tests/tps/test_bug546807.js
@@ -0,0 +1,38 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+EnableEngines(["tabs"]);
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in JSON format as it will get parsed by the Python
+ * testrunner. It is parsed by the YAML package, so it relatively flexible.
+ */
+var phases = { phase1: "profile1", phase2: "profile2" };
+
+/*
+ * Tabs data
+ */
+
+var tabs1 = [
+ { uri: "about:config", profile: "profile1" },
+ { uri: "about:credits", profile: "profile1" },
+ {
+ uri: "data:text/html,<html><head><title>Apple</title></head><body>Apple</body></html>",
+ title: "Apple",
+ profile: "profile1",
+ },
+];
+
+var tabs_absent = [
+ { uri: "about:config", profile: "profile1" },
+ { uri: "about:credits", profile: "profile1" },
+];
+
+/*
+ * Test phases
+ */
+
+Phase("phase1", [[Tabs.add, tabs1], [Sync]]);
+
+Phase("phase2", [[Sync], [Tabs.verifyNot, tabs_absent]]);
diff --git a/services/sync/tests/tps/test_bug556509.js b/services/sync/tests/tps/test_bug556509.js
new file mode 100644
index 0000000000..3a46c3c23e
--- /dev/null
+++ b/services/sync/tests/tps/test_bug556509.js
@@ -0,0 +1,32 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+EnableEngines(["bookmarks"]);
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in JSON format as it will get parsed by the Python
+ * testrunner. It is parsed by the YAML package, so it relatively flexible.
+ */
+var phases = { phase1: "profile1", phase2: "profile2" };
+
+// the initial list of bookmarks to add to the browser
+var bookmarks_initial = {
+ menu: [{ folder: "testfolder", description: "it's just me, a test folder" }],
+ "menu/testfolder": [{ uri: "http://www.mozilla.com", title: "Mozilla" }],
+};
+
+/*
+ * Test phases
+ */
+
+// Add a bookmark folder which has a description, and sync.
+Phase("phase1", [
+ [Bookmarks.add, bookmarks_initial],
+ [Bookmarks.verify, bookmarks_initial],
+ [Sync],
+]);
+
+// Sync to profile2 and verify that the bookmark folder is created, along
+// with its description.
+Phase("phase2", [[Sync], [Bookmarks.verify, bookmarks_initial]]);
diff --git a/services/sync/tests/tps/test_bug562515.js b/services/sync/tests/tps/test_bug562515.js
new file mode 100644
index 0000000000..3a1a6cbee2
--- /dev/null
+++ b/services/sync/tests/tps/test_bug562515.js
@@ -0,0 +1,90 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+EnableEngines(["bookmarks"]);
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in JSON format as it will get parsed by the Python
+ * testrunner. It is parsed by the YAML package, so it relatively flexible.
+ */
+var phases = {
+ phase1: "profile1",
+ phase2: "profile2",
+ phase3: "profile1",
+ phase4: "profile2",
+};
+
+/*
+ * Bookmark lists
+ */
+
+// the initial list of bookmarks to add to the browser
+var bookmarks_initial = {
+ menu: [
+ {
+ uri: "http://www.google.com",
+ tags: ["google", "computers", "internet", "www"],
+ },
+ {
+ uri: "http://bugzilla.mozilla.org/show_bug.cgi?id=%s",
+ title: "Bugzilla",
+ keyword: "bz",
+ },
+ { folder: "foldera" },
+ { uri: "http://www.mozilla.com" },
+ { separator: true },
+ { folder: "folderb" },
+ ],
+ "menu/foldera": [
+ { uri: "http://www.yahoo.com", title: "testing Yahoo" },
+ {
+ uri: "http://www.cnn.com",
+ description: "This is a description of the site a at www.cnn.com",
+ },
+ ],
+ "menu/folderb": [{ uri: "http://www.apple.com", tags: ["apple", "mac"] }],
+ toolbar: [
+ {
+ uri: "place:queryType=0&sort=8&maxResults=10&beginTimeRef=1&beginTime=0",
+ title: "Visited Today",
+ },
+ ],
+};
+
+// a list of bookmarks to delete during a 'delete' action
+var bookmarks_to_delete = {
+ menu: [
+ {
+ uri: "http://www.google.com",
+ tags: ["google", "computers", "internet", "www"],
+ },
+ ],
+ "menu/foldera": [{ uri: "http://www.yahoo.com", title: "testing Yahoo" }],
+};
+
+/*
+ * Test phases
+ */
+
+// add bookmarks to profile1 and sync
+Phase("phase1", [
+ [Bookmarks.add, bookmarks_initial],
+ [Bookmarks.verify, bookmarks_initial],
+ [Sync],
+]);
+
+// sync to profile2 and verify that the bookmarks are present
+Phase("phase2", [[Sync], [Bookmarks.verify, bookmarks_initial]]);
+
+// delete some bookmarks from profile1, then sync with "wipe-client"
+// set; finally, verify that the deleted bookmarks were restored.
+Phase("phase3", [
+ [Bookmarks.delete, bookmarks_to_delete],
+ [Bookmarks.verifyNot, bookmarks_to_delete],
+ [Sync, SYNC_WIPE_CLIENT],
+ [Bookmarks.verify, bookmarks_initial],
+]);
+
+// sync profile2 again, verify no bookmarks have been deleted
+Phase("phase4", [[Sync], [Bookmarks.verify, bookmarks_initial]]);
diff --git a/services/sync/tests/tps/test_bug575423.js b/services/sync/tests/tps/test_bug575423.js
new file mode 100644
index 0000000000..53f46db5b7
--- /dev/null
+++ b/services/sync/tests/tps/test_bug575423.js
@@ -0,0 +1,67 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+EnableEngines(["history"]);
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in JSON format as it will get parsed by the Python
+ * testrunner. It is parsed by the YAML package, so it relatively flexible.
+ */
+var phases = { phase1: "profile1", phase2: "profile2" };
+
+/*
+ * History data
+ */
+
+// the history data to add to the browser
+var history1 = [
+ {
+ uri: "http://www.google.com/",
+ title: "Google",
+ visits: [
+ { type: 1, date: 0 },
+ { type: 2, date: -1 },
+ ],
+ },
+ {
+ uri: "http://www.cnn.com/",
+ title: "CNN",
+ visits: [
+ { type: 1, date: -1 },
+ { type: 2, date: -36 },
+ ],
+ },
+];
+
+// Another history data to add to the browser
+var history2 = [
+ {
+ uri: "http://www.mozilla.com/",
+ title: "Mozilla",
+ visits: [
+ { type: 1, date: 0 },
+ { type: 2, date: -36 },
+ ],
+ },
+ {
+ uri: "http://www.google.com/language_tools?hl=en",
+ title: "Language Tools",
+ visits: [
+ { type: 1, date: 0 },
+ { type: 2, date: -40 },
+ ],
+ },
+];
+
+/*
+ * Test phases
+ */
+Phase("phase1", [
+ [History.add, history1],
+ [Sync],
+ [History.add, history2],
+ [Sync],
+]);
+
+Phase("phase2", [[Sync], [History.verify, history2]]);
diff --git a/services/sync/tests/tps/test_client_wipe.js b/services/sync/tests/tps/test_client_wipe.js
new file mode 100644
index 0000000000..e0fb7a97ac
--- /dev/null
+++ b/services/sync/tests/tps/test_client_wipe.js
@@ -0,0 +1,142 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in JSON format as it will get parsed by the Python
+ * testrunner. It is parsed by the YAML package, so it relatively flexible.
+ */
+var phases = { phase1: "profile1", phase2: "profile2", phase3: "profile1" };
+
+/*
+ * Bookmark lists
+ */
+
+// the initial list of bookmarks to add to the browser
+var bookmarks_initial = {
+ toolbar: [
+ { uri: "http://www.google.com", title: "Google" },
+ {
+ uri: "http://www.cnn.com",
+ title: "CNN",
+ changes: {
+ position: "Google",
+ },
+ },
+ { uri: "http://www.mozilla.com", title: "Mozilla" },
+ {
+ uri: "http://www.firefox.com",
+ title: "Firefox",
+ changes: {
+ position: "Mozilla",
+ },
+ },
+ ],
+};
+
+var bookmarks_after_move = {
+ toolbar: [
+ { uri: "http://www.cnn.com", title: "CNN" },
+ { uri: "http://www.google.com", title: "Google" },
+ { uri: "http://www.firefox.com", title: "Firefox" },
+ { uri: "http://www.mozilla.com", title: "Mozilla" },
+ ],
+};
+
+/*
+ * Password data
+ */
+
+// Initial password data
+var passwords_initial = [
+ {
+ hostname: "http://www.example.com",
+ submitURL: "http://login.example.com",
+ username: "joe",
+ password: "secret",
+ usernameField: "uname",
+ passwordField: "pword",
+ changes: {
+ password: "SeCrEt$$$",
+ },
+ },
+ {
+ hostname: "http://www.example.com",
+ realm: "login",
+ username: "jack",
+ password: "secretlogin",
+ },
+];
+
+// Password after first modify action has been performed
+var passwords_after_change = [
+ {
+ hostname: "http://www.example.com",
+ submitURL: "http://login.example.com",
+ username: "joe",
+ password: "SeCrEt$$$",
+ usernameField: "uname",
+ passwordField: "pword",
+ changes: {
+ username: "james",
+ },
+ },
+ {
+ hostname: "http://www.example.com",
+ realm: "login",
+ username: "jack",
+ password: "secretlogin",
+ },
+];
+
+/*
+ * Prefs to use in the test
+ */
+var prefs1 = [
+ { name: "browser.startup.homepage", value: "http://www.getfirefox.com" },
+ { name: "browser.urlbar.maxRichResults", value: 20 },
+ { name: "privacy.clearOnShutdown.siteSettings", value: true },
+];
+
+var prefs2 = [
+ { name: "browser.startup.homepage", value: "http://www.mozilla.com" },
+ { name: "browser.urlbar.maxRichResults", value: 18 },
+ { name: "privacy.clearOnShutdown.siteSettings", value: false },
+];
+
+/*
+ * Test phases
+ */
+
+// Add prefs,passwords and bookmarks to profile1 and sync.
+Phase("phase1", [
+ [Passwords.add, passwords_initial],
+ [Bookmarks.add, bookmarks_initial],
+ [Prefs.modify, prefs1],
+ [Prefs.verify, prefs1],
+ [Sync],
+]);
+
+// Sync profile2 and verify same prefs,passwords and bookmarks are present.
+Phase("phase2", [
+ [Sync],
+ [Prefs.verify, prefs1],
+ [Passwords.verify, passwords_initial],
+ [Bookmarks.verify, bookmarks_initial],
+]);
+
+// Using profile1, change some prefs,bookmarks and pwds, then do another sync with wipe-client.
+// Verify that the cloud's settings are restored, and the recent local changes
+// discarded.
+Phase("phase3", [
+ [Prefs.modify, prefs2],
+ [Passwords.modify, passwords_initial],
+ [Bookmarks.modify, bookmarks_initial],
+ [Prefs.verify, prefs2],
+ [Passwords.verify, passwords_after_change],
+ [Bookmarks.verify, bookmarks_after_move],
+ [Sync, SYNC_WIPE_CLIENT],
+ [Prefs.verify, prefs1],
+ [Passwords.verify, passwords_initial],
+ [Bookmarks.verify, bookmarks_initial],
+]);
diff --git a/services/sync/tests/tps/test_creditcards.js b/services/sync/tests/tps/test_creditcards.js
new file mode 100644
index 0000000000..fea2b8a541
--- /dev/null
+++ b/services/sync/tests/tps/test_creditcards.js
@@ -0,0 +1,62 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/* global Services */
+Services.prefs.setBoolPref("services.sync.engine.creditcards", true);
+
+EnableEngines(["creditcards"]);
+
+var phases = {
+ phase1: "profile1",
+ phase2: "profile2",
+ phase3: "profile1",
+};
+
+const cc1 = [
+ {
+ "cc-name": "John Doe",
+ "cc-number": "4716179744040592",
+ "cc-exp-month": 4,
+ "cc-exp-year": 2050,
+ "unknown-1": "an unknown field from another client",
+ changes: {
+ "cc-exp-year": 2051,
+ },
+ },
+];
+
+const cc1_after = [
+ {
+ "cc-name": "John Doe",
+ "cc-number": "4716179744040592",
+ "cc-exp-month": 4,
+ "cc-exp-year": 2051,
+ "unknown-1": "an unknown field from another client",
+ },
+];
+
+const cc2 = [
+ {
+ "cc-name": "Timothy Berners-Lee",
+ "cc-number": "2221000374457678",
+ "cc-exp-month": 12,
+ "cc-exp-year": 2050,
+ },
+];
+
+Phase("phase1", [[CreditCards.add, cc1], [Sync]]);
+
+Phase("phase2", [
+ [Sync],
+ [CreditCards.verify, cc1],
+ [CreditCards.modify, cc1],
+ [CreditCards.add, cc2],
+ [Sync],
+]);
+
+Phase("phase3", [
+ [Sync],
+ [CreditCards.verifyNot, cc1],
+ [CreditCards.verify, cc1_after],
+ [CreditCards.verify, cc2],
+]);
diff --git a/services/sync/tests/tps/test_existing_bookmarks.js b/services/sync/tests/tps/test_existing_bookmarks.js
new file mode 100644
index 0000000000..cde41a96e6
--- /dev/null
+++ b/services/sync/tests/tps/test_existing_bookmarks.js
@@ -0,0 +1,80 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+EnableEngines(["bookmarks"]);
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in JSON format as it will get parsed by the Python
+ * testrunner. It is parsed by the YAML package, so it relatively flexible.
+ */
+var phases = {
+ phase1: "profile1",
+ phase2: "profile2",
+ phase3: "profile2",
+ phase4: "profile1",
+};
+
+/*
+ * Bookmark lists
+ */
+var bookmarks_initial = {
+ menu: [
+ {
+ uri: "http://www.google.com",
+ title: "Google",
+ changes: {
+ title: "google",
+ },
+ },
+ {
+ uri: "http://bugzilla.mozilla.org/show_bug.cgi?id=%s",
+ title: "Bugzilla",
+ },
+ { uri: "http://www.mozilla.com" },
+ {
+ uri: "http://www.cnn.com",
+ description: "This is a description of the site a at www.cnn.com",
+ changes: {
+ description: "Global news",
+ },
+ },
+ ],
+};
+
+var bookmarks_after = {
+ menu: [
+ { uri: "http://www.google.com", title: "google" },
+ {
+ uri: "http://bugzilla.mozilla.org/show_bug.cgi?id=%s",
+ title: "Bugzilla",
+ },
+ { uri: "http://www.mozilla.com" },
+ { uri: "http://www.cnn.com", description: "Global news" },
+ ],
+};
+
+/*
+ * Test phases
+ */
+
+Phase("phase1", [
+ [Bookmarks.add, bookmarks_initial],
+ [Bookmarks.verify, bookmarks_initial],
+ [Sync],
+]);
+
+Phase("phase2", [
+ [Bookmarks.add, bookmarks_initial],
+ [Bookmarks.verify, bookmarks_initial],
+ [Sync],
+]);
+
+Phase("phase3", [
+ [Bookmarks.verify, bookmarks_initial],
+ [Bookmarks.modify, bookmarks_initial],
+ [Bookmarks.verify, bookmarks_after],
+ [Sync],
+]);
+
+Phase("phase4", [[Sync], [Bookmarks.verify, bookmarks_after]]);
diff --git a/services/sync/tests/tps/test_extstorage.js b/services/sync/tests/tps/test_extstorage.js
new file mode 100644
index 0000000000..cf25187bc3
--- /dev/null
+++ b/services/sync/tests/tps/test_extstorage.js
@@ -0,0 +1,154 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+EnableEngines(["addons"]);
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in JSON format as it will get parsed by the Python
+ * testrunner. It is parsed by the YAML package, so it relatively flexible.
+ */
+var phases = {
+ phase1: "profile1",
+ phase2: "profile2",
+ phase3: "profile1",
+ phase4: "profile2",
+ phase5: "profile1",
+};
+
+/*
+ * Test phases
+ */
+
+Phase("phase1", [
+ [
+ ExtStorage.set,
+ "ext-1",
+ {
+ "key-1": {
+ sub_key_1: "value 1",
+ sub_key_2: "value 2",
+ },
+ "key-2": {
+ sk_1: "v1",
+ sk_2: "v2",
+ },
+ },
+ ],
+ [
+ ExtStorage.verify,
+ "ext-1",
+ null,
+ {
+ "key-1": {
+ sub_key_1: "value 1",
+ sub_key_2: "value 2",
+ },
+ "key-2": {
+ sk_1: "v1",
+ sk_2: "v2",
+ },
+ },
+ ],
+ [Sync],
+]);
+
+Phase("phase2", [
+ [Sync],
+ [
+ ExtStorage.set,
+ "ext-1",
+ {
+ "key-2": "value from profile 2",
+ },
+ ],
+ [
+ ExtStorage.verify,
+ "ext-1",
+ null,
+ {
+ "key-1": {
+ sub_key_1: "value 1",
+ sub_key_2: "value 2",
+ },
+ "key-2": "value from profile 2",
+ },
+ ],
+ [Sync],
+]);
+
+Phase("phase3", [
+ [Sync],
+ [
+ ExtStorage.verify,
+ "ext-1",
+ null,
+ {
+ "key-1": {
+ sub_key_1: "value 1",
+ sub_key_2: "value 2",
+ },
+ "key-2": "value from profile 2",
+ },
+ ],
+ [
+ ExtStorage.set,
+ "ext-1",
+ {
+ "key-2": "value from profile 1",
+ },
+ ],
+ // exit without syncing.
+]);
+
+Phase("phase4", [
+ [Sync],
+ [
+ ExtStorage.verify,
+ "ext-1",
+ null,
+ {
+ "key-1": {
+ sub_key_1: "value 1",
+ sub_key_2: "value 2",
+ },
+ "key-2": "value from profile 2",
+ },
+ ],
+ [
+ ExtStorage.set,
+ "ext-1",
+ {
+ "key-2": "second value from profile 2",
+ },
+ ],
+ [Sync],
+]);
+
+Phase("phase5", [
+ [
+ ExtStorage.verify,
+ "ext-1",
+ null,
+ {
+ "key-1": {
+ sub_key_1: "value 1",
+ sub_key_2: "value 2",
+ },
+ "key-2": "value from profile 1",
+ },
+ ],
+ [Sync],
+ [
+ ExtStorage.verify,
+ "ext-1",
+ null,
+ {
+ "key-1": {
+ sub_key_1: "value 1",
+ sub_key_2: "value 2",
+ },
+ "key-2": "second value from profile 2",
+ },
+ ],
+]);
diff --git a/services/sync/tests/tps/test_formdata.js b/services/sync/tests/tps/test_formdata.js
new file mode 100644
index 0000000000..764b12342f
--- /dev/null
+++ b/services/sync/tests/tps/test_formdata.js
@@ -0,0 +1,63 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+EnableEngines(["forms"]);
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in JSON format as it will get parsed by the Python
+ * testrunner. It is parsed by the YAML package, so it relatively flexible.
+ */
+var phases = {
+ phase1: "profile1",
+ phase2: "profile2",
+ phase3: "profile1",
+ phase4: "profile2",
+};
+
+/*
+ * Form data asset lists: these define form values that are used in the tests.
+ */
+
+var formdata1 = [
+ { fieldname: "testing", value: "success", date: -1 },
+ { fieldname: "testing", value: "failure", date: -2 },
+ { fieldname: "username", value: "joe" },
+];
+
+var formdata2 = [
+ { fieldname: "testing", value: "success", date: -1 },
+ { fieldname: "username", value: "joe" },
+];
+
+var formdata_delete = [{ fieldname: "testing", value: "failure" }];
+
+var formdata_new = [{ fieldname: "new-field", value: "new-value" }];
+/*
+ * Test phases
+ */
+
+Phase("phase1", [
+ [Formdata.add, formdata1],
+ [Formdata.verify, formdata1],
+ [Sync],
+]);
+
+Phase("phase2", [[Sync], [Formdata.verify, formdata1]]);
+
+Phase("phase3", [
+ [Sync],
+ [Formdata.delete, formdata_delete],
+ [Formdata.verifyNot, formdata_delete],
+ [Formdata.verify, formdata2],
+ // add new data after the first Sync, ensuring the tracker works.
+ [Formdata.add, formdata_new],
+ [Sync],
+]);
+
+Phase("phase4", [
+ [Sync],
+ [Formdata.verify, formdata2],
+ [Formdata.verify, formdata_new],
+ [Formdata.verifyNot, formdata_delete],
+]);
diff --git a/services/sync/tests/tps/test_history.js b/services/sync/tests/tps/test_history.js
new file mode 100644
index 0000000000..e1df78c762
--- /dev/null
+++ b/services/sync/tests/tps/test_history.js
@@ -0,0 +1,129 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+EnableEngines(["history"]);
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in JSON format as it will get parsed by the Python
+ * testrunner. It is parsed by the YAML package, so it relatively flexible.
+ */
+var phases = { phase1: "profile1", phase2: "profile2" };
+
+/*
+ * History asset lists: these define history entries that are used during
+ * the test
+ */
+
+// the initial list of history items to add to the browser
+var history1 = [
+ {
+ uri: "http://www.google.com/",
+ title: "Google",
+ visits: [
+ { type: 1, date: 0 },
+ { type: 2, date: -1 },
+ ],
+ },
+ {
+ uri: "http://www.cnn.com/",
+ title: "CNN",
+ visits: [
+ { type: 1, date: -1 },
+ { type: 2, date: -36 },
+ ],
+ },
+ {
+ uri: "http://www.google.com/language_tools?hl=en",
+ title: "Language Tools",
+ visits: [
+ { type: 1, date: 0 },
+ { type: 2, date: -40 },
+ ],
+ },
+ {
+ uri: "http://www.mozilla.com/",
+ title: "Mozilla",
+ visits: [
+ { type: 1, date: 0 },
+ { type: 1, date: -1 },
+ { type: 1, date: -20 },
+ { type: 2, date: -36 },
+ ],
+ },
+];
+
+// a list of items to delete from the history
+var history_to_delete = [
+ { uri: "http://www.cnn.com/" },
+ { begin: -24, end: -1 },
+ { host: "www.google.com" },
+];
+
+// a list which reflects items that should be in the history after
+// the above items are deleted
+var history2 = [
+ {
+ uri: "http://www.mozilla.com/",
+ title: "Mozilla",
+ visits: [
+ { type: 1, date: 0 },
+ { type: 2, date: -36 },
+ ],
+ },
+];
+
+// a list which includes history entries that should not be present
+// after deletion of the history_to_delete entries
+var history_not = [
+ {
+ uri: "http://www.google.com/",
+ title: "Google",
+ visits: [
+ { type: 1, date: 0 },
+ { type: 2, date: -1 },
+ ],
+ },
+ {
+ uri: "http://www.cnn.com/",
+ title: "CNN",
+ visits: [
+ { type: 1, date: -1 },
+ { type: 2, date: -36 },
+ ],
+ },
+ {
+ uri: "http://www.google.com/language_tools?hl=en",
+ title: "Language Tools",
+ visits: [
+ { type: 1, date: 0 },
+ { type: 2, date: -40 },
+ ],
+ },
+ {
+ uri: "http://www.mozilla.com/",
+ title: "Mozilla",
+ visits: [
+ { type: 1, date: -1 },
+ { type: 1, date: -20 },
+ ],
+ },
+];
+
+/*
+ * Test phases
+ * Note: there is no test phase in which deleted history entries are
+ * synced to other clients. This functionality is not supported by
+ * Sync, see bug 446517.
+ */
+
+Phase("phase1", [[History.add, history1], [Sync]]);
+
+Phase("phase2", [
+ [Sync],
+ [History.verify, history1],
+ [History.delete, history_to_delete],
+ [History.verify, history2],
+ [History.verifyNot, history_not],
+ [Sync],
+]);
diff --git a/services/sync/tests/tps/test_history_collision.js b/services/sync/tests/tps/test_history_collision.js
new file mode 100644
index 0000000000..ea428d1051
--- /dev/null
+++ b/services/sync/tests/tps/test_history_collision.js
@@ -0,0 +1,98 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+EnableEngines(["history"]);
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in JSON format as it will get parsed by the Python
+ * testrunner. It is parsed by the YAML package, so it relatively flexible.
+ */
+var phases = {
+ phase1: "profile1",
+ phase2: "profile2",
+ phase3: "profile1",
+ phase4: "profile2",
+};
+
+/*
+ * History lists
+ */
+
+// the initial list of history to add to the browser
+var history1 = [
+ {
+ uri: "http://www.google.com/",
+ title: "Google",
+ visits: [{ type: 1, date: 0 }],
+ },
+ {
+ uri: "http://www.cnn.com/",
+ title: "CNN",
+ visits: [
+ { type: 1, date: -1 },
+ { type: 2, date: -36 },
+ ],
+ },
+ {
+ uri: "http://www.mozilla.com/",
+ title: "Mozilla",
+ visits: [
+ { type: 1, date: 0 },
+ { type: 2, date: -36 },
+ ],
+ },
+];
+
+// the history to delete
+var history_to_delete = [
+ { uri: "http://www.cnn.com/", title: "CNN" },
+ { begin: -36, end: -1 },
+];
+
+var history_not = [
+ {
+ uri: "http://www.cnn.com/",
+ title: "CNN",
+ visits: [
+ { type: 1, date: -1 },
+ { type: 2, date: -36 },
+ ],
+ },
+];
+
+var history_after_delete = [
+ {
+ uri: "http://www.google.com/",
+ title: "Google",
+ visits: [{ type: 1, date: 0 }],
+ },
+ {
+ uri: "http://www.mozilla.com/",
+ title: "Mozilla",
+ visits: [{ type: 1, date: 0 }],
+ },
+];
+
+/*
+ * Test phases
+ */
+
+Phase("phase1", [[History.add, history1], [Sync]]);
+
+Phase("phase2", [[Sync], [History.add, history1], [Sync, SYNC_WIPE_REMOTE]]);
+
+Phase("phase3", [
+ [Sync],
+ [History.verify, history1],
+ [History.delete, history_to_delete],
+ [History.verify, history_after_delete],
+ [History.verifyNot, history_not],
+ [Sync],
+]);
+
+Phase("phase4", [
+ [Sync],
+ [History.verify, history_after_delete],
+ [History.verifyNot, history_not],
+]);
diff --git a/services/sync/tests/tps/test_passwords.js b/services/sync/tests/tps/test_passwords.js
new file mode 100644
index 0000000000..2dfd7de8dd
--- /dev/null
+++ b/services/sync/tests/tps/test_passwords.js
@@ -0,0 +1,119 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+EnableEngines(["passwords"]);
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in JSON format as it will get parsed by the Python
+ * testrunner. It is parsed by the YAML package, so it relatively flexible.
+ */
+var phases = {
+ phase1: "profile1",
+ phase2: "profile2",
+ phase3: "profile1",
+ phase4: "profile2",
+};
+
+/*
+ * Password asset lists: these define password entries that are used during
+ * the test
+ */
+
+// initial password list to be loaded into the browser
+var passwords_initial = [
+ {
+ hostname: "http://www.example.com",
+ submitURL: "http://login.example.com",
+ username: "joe",
+ password: "SeCrEt123",
+ usernameField: "uname",
+ passwordField: "pword",
+ changes: {
+ password: "zippity-do-dah",
+ },
+ },
+ {
+ hostname: "http://www.example.com",
+ realm: "login",
+ username: "joe",
+ password: "secretlogin",
+ },
+];
+
+// expected state of passwords after the changes in the above list are applied
+var passwords_after_first_update = [
+ {
+ hostname: "http://www.example.com",
+ submitURL: "http://login.example.com",
+ username: "joe",
+ password: "zippity-do-dah",
+ usernameField: "uname",
+ passwordField: "pword",
+ },
+ {
+ hostname: "http://www.example.com",
+ realm: "login",
+ username: "joe",
+ password: "secretlogin",
+ },
+];
+
+var passwords_to_delete = [
+ {
+ hostname: "http://www.example.com",
+ realm: "login",
+ username: "joe",
+ password: "secretlogin",
+ },
+];
+
+var passwords_absent = [
+ {
+ hostname: "http://www.example.com",
+ realm: "login",
+ username: "joe",
+ password: "secretlogin",
+ },
+];
+
+// expected state of passwords after the delete operation
+var passwords_after_second_update = [
+ {
+ hostname: "http://www.example.com",
+ submitURL: "http://login.example.com",
+ username: "joe",
+ password: "zippity-do-dah",
+ usernameField: "uname",
+ passwordField: "pword",
+ },
+];
+
+/*
+ * Test phases
+ */
+
+Phase("phase1", [[Passwords.add, passwords_initial], [Sync]]);
+
+Phase("phase2", [
+ [Sync],
+ [Passwords.verify, passwords_initial],
+ [Passwords.modify, passwords_initial],
+ [Passwords.verify, passwords_after_first_update],
+ [Sync],
+]);
+
+Phase("phase3", [
+ [Sync],
+ [Passwords.verify, passwords_after_first_update],
+ [Passwords.delete, passwords_to_delete],
+ [Passwords.verify, passwords_after_second_update],
+ [Passwords.verifyNot, passwords_absent],
+ [Sync],
+]);
+
+Phase("phase4", [
+ [Sync],
+ [Passwords.verify, passwords_after_second_update],
+ [Passwords.verifyNot, passwords_absent],
+]);
diff --git a/services/sync/tests/tps/test_prefs.js b/services/sync/tests/tps/test_prefs.js
new file mode 100644
index 0000000000..3e26e947dd
--- /dev/null
+++ b/services/sync/tests/tps/test_prefs.js
@@ -0,0 +1,35 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+EnableEngines(["prefs"]);
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in JSON format as it will get parsed by the Python
+ * testrunner. It is parsed by the YAML package, so it relatively flexible.
+ */
+var phases = { phase1: "profile1", phase2: "profile2", phase3: "profile1" };
+
+var prefs1 = [
+ { name: "browser.startup.homepage", value: "http://www.getfirefox.com" },
+ { name: "browser.urlbar.maxRichResults", value: 20 },
+ { name: "privacy.clearOnShutdown.siteSettings", value: true },
+];
+
+var prefs2 = [
+ { name: "browser.startup.homepage", value: "http://www.mozilla.com" },
+ { name: "browser.urlbar.maxRichResults", value: 18 },
+ { name: "privacy.clearOnShutdown.siteSettings", value: false },
+];
+
+Phase("phase1", [[Prefs.modify, prefs1], [Prefs.verify, prefs1], [Sync]]);
+
+Phase("phase2", [
+ [Sync],
+ [Prefs.verify, prefs1],
+ [Prefs.modify, prefs2],
+ [Prefs.verify, prefs2],
+ [Sync],
+]);
+
+Phase("phase3", [[Sync], [Prefs.verify, prefs2]]);
diff --git a/services/sync/tests/tps/test_privbrw_passwords.js b/services/sync/tests/tps/test_privbrw_passwords.js
new file mode 100644
index 0000000000..dcde6c02b8
--- /dev/null
+++ b/services/sync/tests/tps/test_privbrw_passwords.js
@@ -0,0 +1,105 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in strict JSON format, as it will get parsed by the Python
+ * testrunner (no single quotes, extra comma's, etc).
+ */
+EnableEngines(["passwords"]);
+
+var phases = {
+ phase1: "profile1",
+ phase2: "profile2",
+ phase3: "profile1",
+ phase4: "profile2",
+};
+
+/*
+ * Password data
+ */
+
+// Initial password data
+var passwords_initial = [
+ {
+ hostname: "http://www.example.com",
+ submitURL: "http://login.example.com",
+ username: "joe",
+ password: "secret",
+ usernameField: "uname",
+ passwordField: "pword",
+ changes: {
+ password: "SeCrEt$$$",
+ },
+ },
+ {
+ hostname: "http://www.example.com",
+ realm: "login",
+ username: "jack",
+ password: "secretlogin",
+ },
+];
+
+// Password after first modify action has been performed
+var passwords_after_first_change = [
+ {
+ hostname: "http://www.example.com",
+ submitURL: "http://login.example.com",
+ username: "joe",
+ password: "SeCrEt$$$",
+ usernameField: "uname",
+ passwordField: "pword",
+ changes: {
+ username: "james",
+ },
+ },
+ {
+ hostname: "http://www.example.com",
+ realm: "login",
+ username: "jack",
+ password: "secretlogin",
+ },
+];
+
+// Password after second modify action has been performed
+var passwords_after_second_change = [
+ {
+ hostname: "http://www.example.com",
+ submitURL: "http://login.example.com",
+ username: "james",
+ password: "SeCrEt$$$",
+ usernameField: "uname",
+ passwordField: "pword",
+ },
+ {
+ hostname: "http://www.example.com",
+ realm: "login",
+ username: "jack",
+ password: "secretlogin",
+ },
+];
+
+/*
+ * Test phases
+ */
+
+Phase("phase1", [[Passwords.add, passwords_initial], [Sync]]);
+
+Phase("phase2", [
+ [Sync],
+ [Passwords.verify, passwords_initial],
+ [Passwords.modify, passwords_initial],
+ [Passwords.verify, passwords_after_first_change],
+ [Sync],
+]);
+
+Phase("phase3", [
+ [Sync],
+ [Windows.add, { private: true }],
+ [Passwords.verify, passwords_after_first_change],
+ [Passwords.modify, passwords_after_first_change],
+ [Passwords.verify, passwords_after_second_change],
+ [Sync],
+]);
+
+Phase("phase4", [[Sync], [Passwords.verify, passwords_after_second_change]]);
diff --git a/services/sync/tests/tps/test_privbrw_tabs.js b/services/sync/tests/tps/test_privbrw_tabs.js
new file mode 100644
index 0000000000..c7c877677f
--- /dev/null
+++ b/services/sync/tests/tps/test_privbrw_tabs.js
@@ -0,0 +1,86 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in strict JSON format, as it will get parsed by the Python
+ * testrunner (no single quotes, extra comma's, etc).
+ */
+EnableEngines(["tabs"]);
+
+var phases = {
+ phase1: "profile1",
+ phase2: "profile2",
+ phase3: "profile1",
+ phase4: "profile2",
+};
+
+/*
+ * Tabs data
+ */
+
+var tabs1 = [
+ {
+ uri: "data:text/html,<html><head><title>Firefox</title></head><body>Firefox</body></html>",
+ title: "Firefox",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Weave</title></head><body>Weave</body></html>",
+ title: "Weave",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Apple</title></head><body>Apple</body></html>",
+ title: "Apple",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>IRC</title></head><body>IRC</body></html>",
+ title: "IRC",
+ profile: "profile1",
+ },
+];
+
+var tabs2 = [
+ {
+ uri: "data:text/html,<html><head><title>Tinderbox</title></head><body>Tinderbox</body></html>",
+ title: "Tinderbox",
+ profile: "profile2",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Fox</title></head><body>Fox</body></html>",
+ title: "Fox",
+ profile: "profile2",
+ },
+];
+
+var tabs3 = [
+ {
+ uri: "data:text/html,<html><head><title>Jetpack</title></head><body>Jetpack</body></html>",
+ title: "Jetpack",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Selenium</title></head><body>Selenium</body></html>",
+ title: "Selenium",
+ profile: "profile1",
+ },
+];
+
+/*
+ * Test phases
+ */
+
+Phase("phase1", [[Tabs.add, tabs1], [Sync]]);
+
+Phase("phase2", [[Sync], [Tabs.verify, tabs1], [Tabs.add, tabs2], [Sync]]);
+
+Phase("phase3", [
+ [Sync],
+ [Windows.add, { private: true }],
+ [Tabs.add, tabs3],
+ [Sync],
+]);
+
+Phase("phase4", [[Sync], [Tabs.verifyNot, tabs3]]);
diff --git a/services/sync/tests/tps/test_special_tabs.js b/services/sync/tests/tps/test_special_tabs.js
new file mode 100644
index 0000000000..84d336772d
--- /dev/null
+++ b/services/sync/tests/tps/test_special_tabs.js
@@ -0,0 +1,63 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Bug 532173 - Dont sync tabs like about:* , weave firstrun etc
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in strict JSON format, as it will get parsed by the Python
+ * testrunner (no single quotes, extra comma's, etc).
+ */
+EnableEngines(["tabs"]);
+
+var phases = { phase1: "profile1", phase2: "profile2" };
+
+var tabs1 = [
+ {
+ uri: "data:text/html,<html><head><title>Firefox</title></head><body>Firefox</body></html>",
+ title: "Firefox",
+ profile: "profile1",
+ },
+ { uri: "about:plugins", title: "About", profile: "profile1" },
+ { uri: "about:credits", title: "Credits", profile: "profile1" },
+ {
+ uri: "data:text/html,<html><head><title>Mozilla</title></head><body>Mozilla</body></html>",
+ title: "Mozilla",
+ profile: "profile1",
+ },
+ {
+ uri: "http://www.mozilla.com/en-US/firefox/sync/firstrun.html",
+ title: "Firstrun",
+ profile: "profile1",
+ },
+];
+
+var tabs2 = [
+ {
+ uri: "data:text/html,<html><head><title>Firefox</title></head><body>Firefox</body></html>",
+ title: "Firefox",
+ profile: "profile1",
+ },
+ {
+ uri: "data:text/html,<html><head><title>Mozilla</title></head><body>Mozilla</body></html>",
+ title: "Mozilla",
+ profile: "profile1",
+ },
+];
+
+var tabs3 = [
+ {
+ uri: "http://www.mozilla.com/en-US/firefox/sync/firstrun.html",
+ title: "Firstrun",
+ profile: "profile1",
+ },
+ { uri: "about:plugins", title: "About", profile: "profile1" },
+ { uri: "about:credits", title: "Credits", profile: "profile1" },
+];
+
+/*
+ * Test phases
+ */
+Phase("phase1", [[Tabs.add, tabs1], [Sync]]);
+
+Phase("phase2", [[Sync], [Tabs.verify, tabs2], [Tabs.verifyNot, tabs3]]);
diff --git a/services/sync/tests/tps/test_sync.js b/services/sync/tests/tps/test_sync.js
new file mode 100644
index 0000000000..3d14430c60
--- /dev/null
+++ b/services/sync/tests/tps/test_sync.js
@@ -0,0 +1,403 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in strict JSON format, as it will get parsed by the Python
+ * testrunner (no single quotes, extra comma's, etc).
+ */
+
+var phases = {
+ phase1: "profile1",
+ phase2: "profile2",
+ phase3: "profile1",
+ phase4: "profile2",
+};
+
+/*
+ * Bookmark asset lists: these define bookmarks that are used during the test
+ */
+
+// the initial list of bookmarks to be added to the browser
+var bookmarks_initial = {
+ menu: [
+ {
+ uri: "http://www.google.com",
+ tags: ["google", "computers", "internet", "www"],
+ changes: {
+ title: "Google",
+ tags: ["google", "computers", "misc"],
+ },
+ },
+ {
+ uri: "http://bugzilla.mozilla.org/show_bug.cgi?id=%s",
+ title: "Bugzilla",
+ keyword: "bz",
+ changes: {
+ keyword: "bugzilla",
+ },
+ },
+ { folder: "foldera" },
+ { uri: "http://www.mozilla.com" },
+ { separator: true },
+ { folder: "folderb" },
+ ],
+ "menu/foldera": [
+ {
+ uri: "http://www.yahoo.com",
+ title: "testing Yahoo",
+ changes: {
+ location: "menu/folderb",
+ },
+ },
+ {
+ uri: "http://www.cnn.com",
+ description: "This is a description of the site a at www.cnn.com",
+ changes: {
+ uri: "http://money.cnn.com",
+ description: "new description",
+ },
+ },
+ ],
+ "menu/folderb": [
+ {
+ uri: "http://www.apple.com",
+ tags: ["apple", "mac"],
+ changes: {
+ uri: "http://www.apple.com/iphone/",
+ title: "iPhone",
+ location: "menu",
+ position: "Google",
+ tags: [],
+ },
+ },
+ ],
+ toolbar: [
+ {
+ uri: "place:queryType=0&sort=8&maxResults=10&beginTimeRef=1&beginTime=0",
+ title: "Visited Today",
+ },
+ ],
+};
+
+// the state of bookmarks after the first 'modify' action has been performed
+// on them
+var bookmarks_after_first_modify = {
+ menu: [
+ {
+ uri: "http://www.apple.com/iphone/",
+ title: "iPhone",
+ before: "Google",
+ tags: [],
+ },
+ {
+ uri: "http://www.google.com",
+ title: "Google",
+ tags: ["google", "computers", "misc"],
+ },
+ {
+ uri: "http://bugzilla.mozilla.org/show_bug.cgi?id=%s",
+ title: "Bugzilla",
+ keyword: "bugzilla",
+ },
+ { folder: "foldera" },
+ { uri: "http://www.mozilla.com" },
+ { separator: true },
+ {
+ folder: "folderb",
+ changes: {
+ location: "menu/foldera",
+ folder: "Folder B",
+ description: "folder description",
+ },
+ },
+ ],
+ "menu/foldera": [
+ {
+ uri: "http://money.cnn.com",
+ title: "http://www.cnn.com",
+ description: "new description",
+ },
+ ],
+ "menu/folderb": [{ uri: "http://www.yahoo.com", title: "testing Yahoo" }],
+ toolbar: [
+ {
+ uri: "place:queryType=0&sort=8&maxResults=10&beginTimeRef=1&beginTime=0",
+ title: "Visited Today",
+ },
+ ],
+};
+
+// a list of bookmarks to delete during a 'delete' action
+var bookmarks_to_delete = {
+ menu: [
+ {
+ uri: "http://www.google.com",
+ title: "Google",
+ tags: ["google", "computers", "misc"],
+ },
+ ],
+};
+
+// the state of bookmarks after the second 'modify' action has been performed
+// on them
+var bookmarks_after_second_modify = {
+ menu: [
+ { uri: "http://www.apple.com/iphone/", title: "iPhone" },
+ {
+ uri: "http://bugzilla.mozilla.org/show_bug.cgi?id=%s",
+ title: "Bugzilla",
+ keyword: "bugzilla",
+ },
+ { folder: "foldera" },
+ { uri: "http://www.mozilla.com" },
+ { separator: true },
+ ],
+ "menu/foldera": [
+ {
+ uri: "http://money.cnn.com",
+ title: "http://www.cnn.com",
+ description: "new description",
+ },
+ { folder: "Folder B", description: "folder description" },
+ ],
+ "menu/foldera/Folder B": [
+ { uri: "http://www.yahoo.com", title: "testing Yahoo" },
+ ],
+};
+
+// a list of bookmarks which should not be present after the last
+// 'delete' and 'modify' actions
+var bookmarks_absent = {
+ menu: [
+ { uri: "http://www.google.com", title: "Google" },
+ { folder: "folderb" },
+ { folder: "Folder B" },
+ ],
+};
+
+/*
+ * History asset lists: these define history entries that are used during
+ * the test
+ */
+
+// the initial list of history items to add to the browser
+var history_initial = [
+ {
+ uri: "http://www.google.com/",
+ title: "Google",
+ visits: [
+ { type: 1, date: 0 },
+ { type: 2, date: -1 },
+ ],
+ },
+ {
+ uri: "http://www.cnn.com/",
+ title: "CNN",
+ visits: [
+ { type: 1, date: -1 },
+ { type: 2, date: -36 },
+ ],
+ },
+ {
+ uri: "http://www.google.com/language_tools?hl=en",
+ title: "Language Tools",
+ visits: [
+ { type: 1, date: 0 },
+ { type: 2, date: -40 },
+ ],
+ },
+ {
+ uri: "http://www.mozilla.com/",
+ title: "Mozilla",
+ visits: [
+ { type: 1, date: 0 },
+ { type: 1, date: -1 },
+ { type: 1, date: -20 },
+ { type: 2, date: -36 },
+ ],
+ },
+];
+
+// a list of history entries to delete during a 'delete' action
+var history_to_delete = [
+ { uri: "http://www.cnn.com/" },
+ { begin: -24, end: -1 },
+ { host: "www.google.com" },
+];
+
+// the expected history entries after the first 'delete' action
+var history_after_delete = [
+ {
+ uri: "http://www.mozilla.com/",
+ title: "Mozilla",
+ visits: [
+ { type: 1, date: 0 },
+ { type: 2, date: -36 },
+ ],
+ },
+];
+
+// history entries expected to not exist after a 'delete' action
+var history_absent = [
+ {
+ uri: "http://www.google.com/",
+ title: "Google",
+ visits: [
+ { type: 1, date: 0 },
+ { type: 2, date: -1 },
+ ],
+ },
+ {
+ uri: "http://www.cnn.com/",
+ title: "CNN",
+ visits: [
+ { type: 1, date: -1 },
+ { type: 2, date: -36 },
+ ],
+ },
+ {
+ uri: "http://www.google.com/language_tools?hl=en",
+ title: "Language Tools",
+ visits: [
+ { type: 1, date: 0 },
+ { type: 2, date: -40 },
+ ],
+ },
+ {
+ uri: "http://www.mozilla.com/",
+ title: "Mozilla",
+ visits: [
+ { type: 1, date: -1 },
+ { type: 1, date: -20 },
+ ],
+ },
+];
+
+/*
+ * Password asset lists: these define password entries that are used during
+ * the test
+ */
+
+// the initial list of passwords to add to the browser
+var passwords_initial = [
+ {
+ hostname: "http://www.example.com",
+ submitURL: "http://login.example.com",
+ username: "joe",
+ password: "SeCrEt123",
+ usernameField: "uname",
+ passwordField: "pword",
+ changes: {
+ password: "zippity-do-dah",
+ },
+ },
+ {
+ hostname: "http://www.example.com",
+ realm: "login",
+ username: "joe",
+ password: "secretlogin",
+ },
+];
+
+// the expected state of passwords after the first 'modify' action
+var passwords_after_first_modify = [
+ {
+ hostname: "http://www.example.com",
+ submitURL: "http://login.example.com",
+ username: "joe",
+ password: "zippity-do-dah",
+ usernameField: "uname",
+ passwordField: "pword",
+ },
+ {
+ hostname: "http://www.example.com",
+ realm: "login",
+ username: "joe",
+ password: "secretlogin",
+ },
+];
+
+// a list of passwords to delete during a 'delete' action
+var passwords_to_delete = [
+ {
+ hostname: "http://www.example.com",
+ realm: "login",
+ username: "joe",
+ password: "secretlogin",
+ },
+];
+
+// a list of passwords expected to be absent after 'delete' and 'modify'
+// actions
+var passwords_absent = [
+ {
+ hostname: "http://www.example.com",
+ realm: "login",
+ username: "joe",
+ password: "secretlogin",
+ },
+];
+
+// the expected state of passwords after the seconds 'modify' action
+var passwords_after_second_modify = [
+ {
+ hostname: "http://www.example.com",
+ submitURL: "http://login.example.com",
+ username: "joe",
+ password: "zippity-do-dah",
+ usernameField: "uname",
+ passwordField: "pword",
+ },
+];
+
+/*
+ * Test phases
+ */
+
+Phase("phase1", [
+ [Bookmarks.add, bookmarks_initial],
+ [Passwords.add, passwords_initial],
+ [History.add, history_initial],
+ [Sync],
+]);
+
+Phase("phase2", [
+ [Sync],
+ [Bookmarks.verify, bookmarks_initial],
+ [Passwords.verify, passwords_initial],
+ [History.verify, history_initial],
+ [Bookmarks.modify, bookmarks_initial],
+ [Passwords.modify, passwords_initial],
+ [History.delete, history_to_delete],
+ [Bookmarks.verify, bookmarks_after_first_modify],
+ [Passwords.verify, passwords_after_first_modify],
+ [History.verify, history_after_delete],
+ [History.verifyNot, history_absent],
+ [Sync],
+]);
+
+Phase("phase3", [
+ [Sync],
+ [Bookmarks.verify, bookmarks_after_first_modify],
+ [Passwords.verify, passwords_after_first_modify],
+ [History.verify, history_after_delete],
+ [Bookmarks.modify, bookmarks_after_first_modify],
+ [Passwords.modify, passwords_after_first_modify],
+ [Bookmarks.delete, bookmarks_to_delete],
+ [Passwords.delete, passwords_to_delete],
+ [Bookmarks.verify, bookmarks_after_second_modify],
+ [Passwords.verify, passwords_after_second_modify],
+ [Bookmarks.verifyNot, bookmarks_absent],
+ [Passwords.verifyNot, passwords_absent],
+ [Sync],
+]);
+
+Phase("phase4", [
+ [Sync],
+ [Bookmarks.verify, bookmarks_after_second_modify],
+ [Passwords.verify, passwords_after_second_modify],
+ [Bookmarks.verifyNot, bookmarks_absent],
+ [Passwords.verifyNot, passwords_absent],
+ [History.verifyNot, history_absent],
+]);
diff --git a/services/sync/tests/tps/test_tabs.js b/services/sync/tests/tps/test_tabs.js
new file mode 100644
index 0000000000..58e8d358cd
--- /dev/null
+++ b/services/sync/tests/tps/test_tabs.js
@@ -0,0 +1,42 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+EnableEngines(["tabs"]);
+
+/*
+ * The list of phases mapped to their corresponding profiles. The object
+ * here must be in JSON format as it will get parsed by the Python
+ * testrunner. It is parsed by the YAML package, so it relatively flexible.
+ */
+var phases = { phase1: "profile1", phase2: "profile2", phase3: "profile1" };
+
+/*
+ * Tab lists.
+ */
+
+var tabs1 = [
+ { uri: "https://www.mozilla.org/en-US/firefox/", profile: "profile1" },
+ {
+ uri: "https://example.com/",
+ title: "Example Domain",
+ profile: "profile1",
+ },
+];
+
+var tabs2 = [
+ { uri: "https://www.mozilla.org/en-US/contribute/", profile: "profile2" },
+ {
+ uri: "https://example.com/",
+ profile: "profile2",
+ },
+];
+
+/*
+ * Test phases
+ */
+
+Phase("phase1", [[Tabs.add, tabs1], [Sync]]);
+
+Phase("phase2", [[Sync], [Tabs.verify, tabs1], [Tabs.add, tabs2], [Sync]]);
+
+Phase("phase3", [[Sync], [Tabs.verify, tabs2]]);