Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: os == 'android'
- Manifest: toolkit/components/places/tests/queries/xpcshell.toml
/* Any copyright is dedicated to the Public Domain.
// This test ensures that download history (filtered by transition) queries
// don't invalidate (and requery) too often.
function accumulateNotifications(result) {
let notifications = [];
let resultObserver = new Proxy(NavHistoryResultObserver, {
get(target, name) {
if (name == "check") {
result.removeObserver(resultObserver, false);
return expectedNotifications =>
Assert.deepEqual(notifications, expectedNotifications);
}
// ignore a few uninteresting notifications.
if (["QueryInterface", "containerStateChanged"].includes(name)) {
return () => {};
}
return () => {
notifications.push(name);
};
},
});
result.addObserver(resultObserver, false);
return resultObserver;
}
add_task(async function test_downloadhistory_query_notifications() {
const MAX_RESULTS = 5;
let query = PlacesUtils.history.getNewQuery();
query.setTransitions([PlacesUtils.history.TRANSITIONS.DOWNLOAD]);
let options = PlacesUtils.history.getNewQueryOptions();
options.sortingMode = Ci.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING;
options.maxResults = MAX_RESULTS;
let result = PlacesUtils.history.executeQuery(query, options);
let notifications = accumulateNotifications(result);
let root = PlacesUtils.asContainer(result.root);
root.containerOpen = true;
// Add more maxResults downloads in order.
let transitions = Object.values(PlacesUtils.history.TRANSITIONS);
for (let transition of transitions) {
await PlacesTestUtils.addVisits({
uri,
transition,
title: "test " + transition,
});
// For each visit also set apart:
// - a bookmark
// - an annotation
// - an icon
await PlacesUtils.bookmarks.insert({
url: uri,
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
});
await PlacesUtils.history.update({
url: uri,
annotations: new Map([["test/anno", "testValue"]]),
});
await PlacesTestUtils.addFavicons(new Map([[uri, SMALLPNG_DATA_URI.spec]]));
}
// Remove all the visits one by one.
for (let transition of transitions) {
await PlacesUtils.history.remove(uri);
}
root.containerOpen = false;
// We pretty much don't want to see invalidateContainer here, because that
// means we requeried.
// We also don't want to see changes caused by filtered-out transition types.
notifications.check([
"nodeHistoryDetailsChanged",
"nodeInserted",
"nodeTitleChanged",
"nodeIconChanged",
"nodeRemoved",
]);
});
add_task(async function test_downloadhistory_query_filtering() {
const MAX_RESULTS = 3;
let query = PlacesUtils.history.getNewQuery();
query.setTransitions([PlacesUtils.history.TRANSITIONS.DOWNLOAD]);
let options = PlacesUtils.history.getNewQueryOptions();
options.sortingMode = Ci.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING;
options.maxResults = MAX_RESULTS;
let result = PlacesUtils.history.executeQuery(query, options);
let root = PlacesUtils.asContainer(result.root);
root.containerOpen = true;
Assert.equal(root.childCount, 0, "No visits found");
// Add more than maxResults downloads.
let uris = [];
// Define a monotonic visit date to ensure results order stability.
let visitDate = Date.now() * 1000;
for (let i = 0; i < MAX_RESULTS + 1; ++i, visitDate += 1000) {
await PlacesTestUtils.addVisits({
uri,
transition: PlacesUtils.history.TRANSITIONS.DOWNLOAD,
visitDate,
});
uris.push(uri);
}
// Add an older download visit out of the maxResults timeframe.
await PlacesTestUtils.addVisits({
transition: PlacesUtils.history.TRANSITIONS.DOWNLOAD,
visitDate: new Date(Date.now() - 7200000),
});
Assert.equal(root.childCount, MAX_RESULTS, "Result should be limited");
// Invert the uris array because we are sorted by date descending.
uris.reverse();
for (let i = 0; i < root.childCount; ++i) {
let node = root.getChild(i);
Assert.equal(node.uri, uris[i], "Found the expected uri");
}
root.containerOpen = false;
});