summaryrefslogtreecommitdiffstats
path: root/browser/components/places/tests/browser/browser_bookmark_backup_export_import.js
blob: 8b954a846918911344635cbd01b39221b6a50094 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

/**
 * Tests bookmarks backup export/import as JSON file.
 */

const BASE_URL = "http://example.com/";

const PLACES = [
  {
    guid: PlacesUtils.bookmarks.menuGuid,
    prefix: "In Menu",
    total: 5,
  },
  {
    guid: PlacesUtils.bookmarks.toolbarGuid,
    prefix: "In Toolbar",
    total: 7,
  },
  {
    guid: PlacesUtils.bookmarks.unfiledGuid,
    prefix: "In Other",
    total: 8,
  },
];

var importExportPicker, saveDir, actualBookmarks;

async function generateTestBookmarks() {
  actualBookmarks = [];
  for (let place of PLACES) {
    let currentPlaceChildren = [];
    for (let i = 1; i <= place.total; i++) {
      currentPlaceChildren.push({
        url: `${BASE_URL}${i}`,
        title: `${place.prefix} Bookmark: ${i}`,
      });
    }
    await PlacesUtils.bookmarks.insertTree({
      guid: place.guid,
      children: currentPlaceChildren,
    });
    actualBookmarks = actualBookmarks.concat(currentPlaceChildren);
  }
}

async function validateImportedBookmarksByParent(
  parentGuid,
  expectedChildrenTotal
) {
  let currentPlace = PLACES.filter(elem => {
    return elem.guid === parentGuid.toString();
  })[0];

  let bookmarksTree = await PlacesUtils.promiseBookmarksTree(parentGuid);

  Assert.equal(
    bookmarksTree.children.length,
    expectedChildrenTotal,
    `Imported bookmarks length should be ${expectedChildrenTotal}`
  );

  for (let importedBookmark of bookmarksTree.children) {
    Assert.equal(
      importedBookmark.type,
      PlacesUtils.TYPE_X_MOZ_PLACE,
      `Exported bookmarks should be of type bookmark`
    );

    let doesTitleContain = importedBookmark.title
      .toString()
      .includes(`${currentPlace.prefix} Bookmark`);
    Assert.equal(
      doesTitleContain,
      true,
      `Bookmark title should contain text: ${currentPlace.prefix} Bookmark`
    );

    let doesUriContains = importedBookmark.uri.toString().includes(BASE_URL);
    Assert.equal(doesUriContains, true, "Bookmark uri should contain base url");
  }
}

async function validateImportedBookmarks(fromPlaces) {
  for (let i = 0; i < fromPlaces.length; i++) {
    let parentContainer = fromPlaces[i];
    await validateImportedBookmarksByParent(
      parentContainer.guid,
      parentContainer.total
    );
  }
}

async function promiseImportExport(aWindow) {
  saveDir = Services.dirsvc.get("TmpD", Ci.nsIFile);
  saveDir.append("temp-bookmarks-export");
  if (!saveDir.exists()) {
    saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
  }
  importExportPicker.displayDirectory = saveDir;

  return new Promise(resolve => {
    importExportPicker.showCallback = async () => {
      let fileName = "bookmarks-backup.json";
      let destFile = saveDir.clone();
      destFile.append(fileName);
      importExportPicker.setFiles([destFile]);
      resolve(destFile);
    };
  });
}

add_setup(async function () {
  await promisePlacesInitComplete();
  await PlacesUtils.bookmarks.eraseEverything();
  await generateTestBookmarks();
  importExportPicker = SpecialPowers.MockFilePicker;
  importExportPicker.init(window);

  registerCleanupFunction(async () => {
    importExportPicker.cleanup();
    await PlacesUtils.bookmarks.eraseEverything();
  });
});

async function showMaintenancePopup(libraryWindow) {
  let button = libraryWindow.document.getElementById("maintenanceButton");
  let popup = libraryWindow.document.getElementById("maintenanceButtonPopup");
  let shown = BrowserTestUtils.waitForEvent(popup, "popupshown");

  info("Clicking maintenance menu");

  button.openMenu(true);

  await shown;
  info("Maintenance popup shown");
  return popup;
}

add_task(async function test_export_json() {
  let libraryWindow = await promiseLibrary();
  let popup = await showMaintenancePopup(libraryWindow);
  let hidden = BrowserTestUtils.waitForEvent(popup, "popuphidden");

  info("Activating #backupBookmarks");

  let backupPromise = promiseImportExport();

  popup.activateItem(popup.querySelector("#backupBookmarks"));
  await hidden;

  info("Popup hidden");

  let backupFile = await backupPromise;
  await TestUtils.waitForCondition(
    backupFile.exists,
    "Backup file should exist"
  );
  await promiseLibraryClosed(libraryWindow);

  await PlacesUtils.bookmarks.eraseEverything();
});

async function showFileRestorePopup(libraryWindow) {
  let parentPopup = await showMaintenancePopup(libraryWindow);
  let popup = parentPopup.querySelector("#fileRestorePopup");
  let shown = BrowserTestUtils.waitForEvent(popup, "popupshown");
  parentPopup.querySelector("#fileRestoreMenu").openMenu(true);
  await shown;
  return popup;
}

add_task(async function test_import_json() {
  let libraryWindow = await promiseLibrary();
  let popup = await showFileRestorePopup(libraryWindow);

  let backupPromise = promiseImportExport();
  let dialogPromise = BrowserTestUtils.promiseAlertDialogOpen("accept");

  let hidden = BrowserTestUtils.waitForEvent(popup, "popuphidden");
  popup.activateItem(popup.querySelector("#restoreFromFile"));
  await hidden;

  await backupPromise;
  await dialogPromise;

  let restored = 0;
  let promiseBookmarksRestored = PlacesTestUtils.waitForNotification(
    "bookmark-added",
    events => events.some(() => ++restored == actualBookmarks.length)
  );

  await promiseBookmarksRestored;
  await validateImportedBookmarks(PLACES);
  await promiseLibraryClosed(libraryWindow);

  registerCleanupFunction(async () => {
    if (saveDir) {
      saveDir.remove(true);
    }
  });
});