Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: os == 'android'
- Manifest: browser/components/pagedata/tests/unit/xpcshell.toml
/* Any copyright is dedicated to the Public Domain.
ChromeUtils.defineESModuleGetters(this, {
PageDataService: "resource:///modules/pagedata/PageDataService.sys.mjs",
});
// Test that urls are retrieved in the expected order.
add_task(async function test_queueOrder() {
Services.prefs.setIntPref("browser.pagedata.maxBackgroundFetches", 0);
// Pretend we are idle.
PageDataService.observe(null, "idle", null);
let pageDataResults = [
{
date: Date.now(),
siteName: "Mozilla",
data: {},
},
{
date: Date.now() - 3600,
siteName: "Google",
data: {},
},
{
date: Date.now() + 3600,
data: {},
},
{
date: Date.now() / 2,
data: {},
},
{
date: Date.now() / 3,
data: {
[PageDataSchema.DATA_TYPE.PRODUCT]: {
name: "Windows 11",
},
},
},
];
let requests = [];
PageDataService.fetchPageData = url => {
requests.push(url);
for (let pageData of pageDataResults) {
if (pageData.url == url) {
return Promise.resolve(pageData);
}
}
return Promise.reject(new Error("Unknown url"));
};
let { promise: completePromise, resolve } = Promise.withResolvers();
let results = [];
let listener = (_, pageData) => {
results.push(pageData);
if (results.length == pageDataResults.length) {
resolve();
}
};
PageDataService.on("page-data", listener);
for (let pageData of pageDataResults) {
PageDataService.queueFetch(pageData.url);
}
await completePromise;
PageDataService.off("page-data", listener);
Assert.deepEqual(
requests,
pageDataResults.map(pd => pd.url)
);
// Because our fetch implementation is essentially synchronous the results
// will be in a known order. This isn't guaranteed by the API though.
Assert.deepEqual(results, pageDataResults);
delete PageDataService.fetchPageData;
});
// Tests that limiting the number of fetches works.
add_task(async function test_queueLimit() {
Services.prefs.setIntPref("browser.pagedata.maxBackgroundFetches", 3);
// Pretend we are idle.
PageDataService.observe(null, "idle", null);
let requests = [];
PageDataService.fetchPageData = url => {
let { promise, resolve, reject } = Promise.withResolvers();
requests.push({ url, resolve, reject });
return promise;
};
let results = [];
let listener = (_, pageData) => {
results.push(pageData?.url);
};
PageDataService.on("page-data", listener);
await TestUtils.waitForTick();
Assert.deepEqual(
requests.map(r => r.url),
[
]
);
// Completing or rejecting a request should start new ones.
requests[1].resolve({
date: 2345,
siteName: "Test 2",
data: {},
});
await TestUtils.waitForTick();
Assert.deepEqual(
requests.map(r => r.url),
[
]
);
requests[3].reject(new Error("Fail"));
await TestUtils.waitForTick();
Assert.deepEqual(
requests.map(r => r.url),
[
]
);
// Increasing the limit should start more requests.
Services.prefs.setIntPref("browser.pagedata.maxBackgroundFetches", 5);
await TestUtils.waitForTick();
Assert.deepEqual(
requests.map(r => r.url),
[
]
);
// Dropping the limit shouldn't start anything new.
Services.prefs.setIntPref("browser.pagedata.maxBackgroundFetches", 3);
await TestUtils.waitForTick();
Assert.deepEqual(
requests.map(r => r.url),
[
]
);
// But resolving should also not start new requests.
requests[5].resolve({
date: 345334,
siteName: "Test 6",
data: {},
});
requests[0].resolve({
date: 343446434,
siteName: "Test 1",
data: {},
});
await TestUtils.waitForTick();
Assert.deepEqual(
requests.map(r => r.url),
[
]
);
// Until a previous request completes.
requests[4].resolve(null);
await TestUtils.waitForTick();
Assert.deepEqual(
requests.map(r => r.url),
[
]
);
// Inifinite queue should work.
Services.prefs.setIntPref("browser.pagedata.maxBackgroundFetches", 0);
await TestUtils.waitForTick();
Assert.deepEqual(
requests.map(r => r.url),
[
]
);
requests[10].resolve({
date: 345334,
data: {},
});
requests[2].resolve({
date: 345334,
data: {},
});
requests[7].resolve({
date: 345334,
data: {},
});
requests[6].resolve({
date: 345334,
data: {},
});
requests[8].resolve({
date: 345334,
data: {},
});
requests[9].resolve({
date: 345334,
data: {},
});
await TestUtils.waitForTick();
Assert.deepEqual(
requests.map(r => r.url),
[
]
);
PageDataService.off("page-data", listener);
delete PageDataService.fetchPageData;
Assert.deepEqual(results, [
]);
});
// Tests that the user idle state stops and starts fetches.
add_task(async function test_idle() {
Services.prefs.setIntPref("browser.pagedata.maxBackgroundFetches", 3);
// Pretend we are active.
PageDataService.observe(null, "active", null);
let requests = [];
PageDataService.fetchPageData = url => {
let { promise, resolve, reject } = Promise.withResolvers();
requests.push({ url, resolve, reject });
return promise;
};
let results = [];
let listener = (_, pageData) => {
results.push(pageData?.url);
};
PageDataService.on("page-data", listener);
await TestUtils.waitForTick();
// Nothing will start when active.
Assert.deepEqual(
requests.map(r => r.url),
[]
);
// Pretend we are idle.
PageDataService.observe(null, "idle", null);
await TestUtils.waitForTick();
Assert.deepEqual(
requests.map(r => r.url),
[
]
);
// Completing or rejecting a request should start new ones.
requests[1].resolve({
date: 2345,
data: {},
});
await TestUtils.waitForTick();
Assert.deepEqual(
requests.map(r => r.url),
[
]
);
// But not when active
PageDataService.observe(null, "active", null);
requests[3].resolve({
date: 2345,
data: {},
});
requests[0].resolve({
date: 2345,
data: {},
});
requests[2].resolve({
date: 2345,
data: {},
});
await TestUtils.waitForTick();
Assert.deepEqual(
requests.map(r => r.url),
[
]
);
// Going idle should start more workers
PageDataService.observe(null, "idle", null);
await TestUtils.waitForTick();
Assert.deepEqual(
requests.map(r => r.url),
[
]
);
requests[4].resolve({
date: 2345,
data: {},
});
requests[5].resolve({
date: 2345,
data: {},
});
requests[6].resolve({
date: 2345,
data: {},
});
await TestUtils.waitForTick();
Assert.deepEqual(
requests.map(r => r.url),
[
]
);
PageDataService.off("page-data", listener);
delete PageDataService.fetchPageData;
Assert.deepEqual(results, [
]);
});