Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* Any copyright is dedicated to the Public Domain.
"use strict";
ChromeUtils.defineESModuleGetters(this, {
});
const SHOW_SPONSORED_PREF = "showSponsoredTopSites";
const TOP_SITES_BLOCKED_SPONSORS_PREF = "browser.topsites.blockedSponsors";
const CONTILE_CACHE_PREF = "browser.topsites.contile.cachedTiles";
const CONTILE_CACHE_VALID_FOR_PREF = "browser.topsites.contile.cacheValidFor";
const CONTILE_CACHE_LAST_FETCH_PREF = "browser.topsites.contile.lastFetch";
const NIMBUS_VARIABLE_MAX_SPONSORED = "topSitesMaxSponsored";
const NIMBUS_VARIABLE_CONTILE_POSITIONS = "contileTopsitesPositions";
const NIMBUS_VARIABLE_CONTILE_ENABLED = "topSitesContileEnabled";
const NIMBUS_VARIABLE_CONTILE_MAX_NUM_SPONSORED = "topSitesContileMaxSponsored";
let contileTile1 = {
id: 74357,
name: "Brand1",
click_url: "https://clickurl.com",
image_size: 200,
impression_url: "https://impression_url.com",
};
let contileTile2 = {
id: 74925,
name: "Brand2",
click_url: "https://click_url.com",
image_size: 200,
impression_url: "https://impression_url.com",
};
let contileTile3 = {
id: 75001,
name: "Brand3",
click_url: "https://click_url.com",
image_size: 200,
impression_url: "https://impression_url.com",
};
let mozSalesTile = [
{
label: "MozSales Title",
title: "MozSales Title",
sponsored_position: 1,
partner: "moz-sales",
},
];
function getTopSitesFeedForTest(sandbox) {
let feed = new TopSitesFeed();
const storage = {
init: sandbox.stub().resolves(),
get: sandbox.stub().resolves(),
set: sandbox.stub().resolves(),
};
feed._storage = storage;
feed.store = {
dispatch: sinon.spy(),
getState() {
return this.state;
},
state: {
Prefs: { values: { topSitesRows: 2 } },
TopSites: { rows: Array(12).fill("site") },
},
dbStorage: { getDbTable: sandbox.stub().returns(storage) },
};
return feed;
}
function prepFeed(feed, sandbox) {
feed.store.state.Prefs.values[SHOW_SPONSORED_PREF] = true;
let fetchStub = sandbox.stub(feed, "fetch");
return { feed, fetchStub };
}
function setNimbusVariablesForNumTiles(nimbusPocketStub, numTiles) {
nimbusPocketStub.withArgs(NIMBUS_VARIABLE_MAX_SPONSORED).returns(numTiles);
nimbusPocketStub
.withArgs(NIMBUS_VARIABLE_CONTILE_MAX_NUM_SPONSORED)
.returns(numTiles);
// when setting num tiles to > 2 need to set the positions or the > 2 has no effect.
// can be defaulted to undefined
let positionsArray = Array.from(
{ length: numTiles },
(value, index) => index
);
nimbusPocketStub
.withArgs(NIMBUS_VARIABLE_CONTILE_POSITIONS)
.returns(positionsArray.toString());
}
add_setup(async () => {
do_get_profile();
Services.fog.initializeFOG();
let sandbox = sinon.createSandbox();
sandbox.stub(SearchService.prototype, "init").resolves();
const nimbusStub = sandbox.stub(NimbusFeatures.newtab, "getVariable");
nimbusStub.withArgs(NIMBUS_VARIABLE_CONTILE_ENABLED).returns(true);
sandbox.spy(Glean.topsites.sponsoredTilesConfigured, "set");
sandbox.spy(Glean.topsites.sponsoredTilesReceived, "set");
// Temporarily setting isInAutomation to false.
// If Cu.isInAutomation is true then the check for Cu.isInAutomation in
// ContileIntegration._readDefaults passes, bypassing Contile, resulting in
// not being able use stubbed values.
if (Cu.isInAutomation) {
Services.prefs.setBoolPref(
"security.turn_off_all_security_so_that_viruses_can_take_over_this_computer",
false
);
if (Cu.isInAutomation) {
// This condition is unexpected, because it is enforced at:
throw new Error("Failed to set isInAutomation to false");
}
}
registerCleanupFunction(() => {
if (!Cu.isInAutomation) {
Services.prefs.setBoolPref(
"security.turn_off_all_security_so_that_viruses_can_take_over_this_computer",
true
);
if (!Cu.isInAutomation) {
// This condition is unexpected, because it is enforced at:
throw new Error("Failed to set isInAutomation to true");
}
}
sandbox.restore();
});
});
add_task(async function test_set_contile_tile_to_oversold() {
let sandbox = sinon.createSandbox();
let feed = getTopSitesFeedForTest(sandbox);
feed._telemetryUtility.setSponsoredTilesConfigured();
feed._telemetryUtility.setTiles([contileTile1, contileTile2, contileTile3]);
let mergedTiles = [
{
label: "brand1",
sponsored_position: 1,
partner: "amp",
},
{
label: "brand2",
sponsored_position: 2,
partner: "amp",
},
];
feed._telemetryUtility.determineFilteredTilesAndSetToOversold(mergedTiles);
feed._telemetryUtility.finalizeNewtabPingFields(mergedTiles);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 2);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "brand1",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand2",
provider: "amp",
display_position: 2,
display_fail_reason: null,
},
{
advertiser: "brand3",
provider: "amp",
display_position: null,
display_fail_reason: "oversold",
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
sandbox.restore();
});
add_task(async function test_set_moz_sale_tile_to_oversold() {
let sandbox = sinon.createSandbox();
info(
"determineFilteredTilesAndSetToOversold should set moz-sale tile to oversold when_contile tiles are displayed"
);
let feed = getTopSitesFeedForTest(sandbox);
feed._telemetryUtility.setSponsoredTilesConfigured();
feed._telemetryUtility.setTiles([contileTile1, contileTile2]);
feed._telemetryUtility.setTiles(mozSalesTile);
let mergedTiles = [
{
label: "brand1",
sponsored_position: 1,
partner: "amp",
},
{
label: "brand2",
sponsored_position: 2,
partner: "amp",
},
];
feed._telemetryUtility.determineFilteredTilesAndSetToOversold(mergedTiles);
feed._telemetryUtility.finalizeNewtabPingFields(mergedTiles);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "brand1",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand2",
provider: "amp",
display_position: 2,
display_fail_reason: null,
},
{
advertiser: "mozsales title",
provider: "moz-sales",
display_position: null,
display_fail_reason: "oversold",
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
sandbox.restore();
});
add_task(async function test_set_contile_tile_to_oversold() {
let sandbox = sinon.createSandbox();
info(
"determineFilteredTilesAndSetToOversold should set contile tile to oversold when moz-sale tile is displayed"
);
let feed = getTopSitesFeedForTest(sandbox);
feed._telemetryUtility.setSponsoredTilesConfigured();
feed._telemetryUtility.setTiles([contileTile1, contileTile2]);
feed._telemetryUtility.setTiles(mozSalesTile);
let mergedTiles = [
{
label: "brand1",
sponsored_position: 1,
partner: "amp",
},
{
label: "MozSales Title",
title: "MozSales Title",
sponsored_position: 2,
partner: "moz-sales",
},
];
feed._telemetryUtility.determineFilteredTilesAndSetToOversold(mergedTiles);
feed._telemetryUtility.finalizeNewtabPingFields(mergedTiles);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "brand1",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand2",
provider: "amp",
display_position: null,
display_fail_reason: "oversold",
},
{
advertiser: "mozsales title",
provider: "moz-sales",
display_position: 2,
display_fail_reason: null,
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
sandbox.restore();
});
add_task(async function test_set_contile_tiles_to_dismissed() {
let sandbox = sinon.createSandbox();
let feed = getTopSitesFeedForTest(sandbox);
feed._telemetryUtility.setSponsoredTilesConfigured();
feed._telemetryUtility.setTiles([contileTile1, contileTile2, contileTile3]);
let mergedTiles = [
{
label: "brand1",
sponsored_position: 1,
partner: "amp",
},
{
label: "brand2",
sponsored_position: 2,
partner: "amp",
},
];
feed._telemetryUtility.determineFilteredTilesAndSetToDismissed(mergedTiles);
feed._telemetryUtility.finalizeNewtabPingFields(mergedTiles);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "brand1",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand2",
provider: "amp",
display_position: 2,
display_fail_reason: null,
},
{
advertiser: "brand3",
provider: "amp",
display_position: null,
display_fail_reason: "dismissed",
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
sandbox.restore();
});
add_task(async function test_set_all_contile_tiles_to_dismissed() {
let sandbox = sinon.createSandbox();
let feed = getTopSitesFeedForTest(sandbox);
feed._telemetryUtility.setSponsoredTilesConfigured();
feed._telemetryUtility.setTiles([contileTile1, contileTile2, contileTile3]);
let mergedTiles = [];
feed._telemetryUtility.determineFilteredTilesAndSetToDismissed(mergedTiles);
feed._telemetryUtility.finalizeNewtabPingFields(mergedTiles);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "brand1",
provider: "amp",
display_position: null,
display_fail_reason: "dismissed",
},
{
advertiser: "brand2",
provider: "amp",
display_position: null,
display_fail_reason: "dismissed",
},
{
advertiser: "brand3",
provider: "amp",
display_position: null,
display_fail_reason: "dismissed",
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
sandbox.restore();
});
add_task(async function test_set_moz_sales_tiles_to_dismissed() {
let sandbox = sinon.createSandbox();
let feed = getTopSitesFeedForTest(sandbox);
feed._telemetryUtility.setSponsoredTilesConfigured();
feed._telemetryUtility.setTiles([contileTile1, contileTile2]);
feed._telemetryUtility.setTiles(mozSalesTile);
let mergedTiles = [
{
label: "brand1",
sponsored_position: 1,
partner: "amp",
},
{
label: "brand2",
sponsored_position: 2,
partner: "amp",
},
];
feed._telemetryUtility.determineFilteredTilesAndSetToDismissed(mergedTiles);
feed._telemetryUtility.finalizeNewtabPingFields(mergedTiles);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "brand1",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand2",
provider: "amp",
display_position: 2,
display_fail_reason: null,
},
{
advertiser: "mozsales title",
provider: "moz-sales",
display_position: null,
display_fail_reason: "dismissed",
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
sandbox.restore();
});
add_task(async function test_set_tiles_to_dismissed_then_updated() {
let sandbox = sinon.createSandbox();
let feed = getTopSitesFeedForTest(sandbox);
feed._telemetryUtility.setSponsoredTilesConfigured();
// Step 1: Set initial tiles
feed._telemetryUtility.setTiles([contileTile1, contileTile2, contileTile3]);
// Step 2: Set all tiles to dismissed
feed._telemetryUtility.determineFilteredTilesAndSetToDismissed([]);
let updatedTiles = [
{
label: "brand1",
sponsored_position: 1,
partner: "amp",
},
{
label: "brand2",
sponsored_position: 2,
partner: "amp",
},
];
// Step 3: Finalize with the updated list of tiles.
feed._telemetryUtility.finalizeNewtabPingFields(updatedTiles);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 2);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "brand1",
provider: "amp",
display_position: null,
display_fail_reason: "dismissed",
},
{
advertiser: "brand2",
provider: "amp",
display_position: null,
display_fail_reason: "dismissed",
},
{
advertiser: "brand3",
provider: "amp",
display_position: null,
display_fail_reason: "dismissed",
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
sandbox.restore();
});
add_task(async function test_set_tile_positions_after_updated_list() {
let sandbox = sinon.createSandbox();
let feed = getTopSitesFeedForTest(sandbox);
feed._telemetryUtility.setSponsoredTilesConfigured();
// Step 1: Set initial tiles
feed._telemetryUtility.setTiles([contileTile1, contileTile2, contileTile3]);
// Step 2: Set 1 tile to oversold (brand3)
let mergedTiles = [
{
label: "brand1",
sponsored_position: 1,
partner: "amp",
},
{
label: "brand2",
sponsored_position: 2,
partner: "amp",
},
];
feed._telemetryUtility.determineFilteredTilesAndSetToOversold(mergedTiles);
// Step 3: Finalize with the updated list of tiles.
let updatedTiles = [
{
label: "replacement",
sponsored_position: 1,
partner: "amp",
},
{
label: "brand2",
sponsored_position: 2,
partner: "amp",
},
];
feed._telemetryUtility.finalizeNewtabPingFields(updatedTiles);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 2);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "brand1",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand2",
provider: "amp",
display_position: 2,
display_fail_reason: null,
},
{
advertiser: "brand3",
provider: "amp",
display_position: null,
display_fail_reason: "oversold",
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
sandbox.restore();
});
add_task(async function test_set_tile_positions_after_updated_list_all_tiles() {
let sandbox = sinon.createSandbox();
let feed = getTopSitesFeedForTest(sandbox);
feed._telemetryUtility.setSponsoredTilesConfigured();
// Step 1: Set initial tiles
feed._telemetryUtility.setTiles([contileTile1, contileTile2, contileTile3]);
// Step 2: Set 1 tile to oversold (brand3)
let mergedTiles = [
{
label: "brand1",
sponsored_position: 1,
partner: "amp",
},
{
label: "brand2",
sponsored_position: 2,
partner: "amp",
},
];
feed._telemetryUtility.determineFilteredTilesAndSetToOversold(mergedTiles);
// Step 3: Finalize with the updated list of tiles.
let updatedTiles = [
{
label: "replacement",
sponsored_position: 1,
partner: "amp",
},
{
label: "replacement2",
sponsored_position: 2,
partner: "amp",
},
];
feed._telemetryUtility.finalizeNewtabPingFields(updatedTiles);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 2);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "brand1",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand2",
provider: "amp",
display_position: 2,
display_fail_reason: null,
},
{
advertiser: "brand3",
provider: "amp",
display_position: null,
display_fail_reason: "oversold",
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
sandbox.restore();
});
add_task(
async function test_set_tile_positions_after_no_refresh_no_tiles_changed() {
let sandbox = sinon.createSandbox();
let feed = getTopSitesFeedForTest(sandbox);
feed._telemetryUtility.setSponsoredTilesConfigured();
// Step 1: Set initial tiles
feed._telemetryUtility.setTiles([contileTile1, contileTile2, contileTile3]);
// Step 2: Set 1 tile to oversold (brand3)
let mergedTiles = [
{
label: "brand1",
sponsored_position: 1,
partner: "amp",
},
{
label: "brand2",
sponsored_position: 2,
partner: "amp",
},
];
feed._telemetryUtility.determineFilteredTilesAndSetToOversold(mergedTiles);
// Step 3: Finalize with the updated list of tiles.
let updatedTiles = [
{
label: "brand1",
sponsored_position: 1,
partner: "amp",
},
{
label: "brand2",
sponsored_position: 2,
partner: "amp",
},
];
feed._telemetryUtility.finalizeNewtabPingFields(updatedTiles);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 2);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "brand1",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand2",
provider: "amp",
display_position: 2,
display_fail_reason: null,
},
{
advertiser: "brand3",
provider: "amp",
display_position: null,
display_fail_reason: "oversold",
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
sandbox.restore();
}
);
add_task(async function test_set_contile_tile_to_unresolved() {
let sandbox = sinon.createSandbox();
let feed = getTopSitesFeedForTest(sandbox);
// Create the error state, need to bypass existing checks.
feed._telemetryUtility.allSponsoredTiles = {
ampbrand1: {
advertiser: "brand1",
provider: "amp",
display_position: 1,
display_fail_reason: "oversold",
},
ampbrand2: {
advertiser: "brand2",
provider: "amp",
display_position: null,
display_fail_reason: null,
},
};
feed._telemetryUtility._detectErrorConditionAndSetUnresolved();
let result = JSON.stringify({
sponsoredTilesReceived: Object.values(
feed._telemetryUtility.allSponsoredTiles
),
});
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "brand1",
provider: "amp",
display_position: null,
display_fail_reason: "unresolved",
},
{
advertiser: "brand2",
provider: "amp",
display_position: null,
display_fail_reason: "unresolved",
},
],
};
Assert.equal(result, JSON.stringify(expectedResult));
sandbox.restore();
});
add_task(async function test_set_position_to_value_gt_3() {
let sandbox = sinon.createSandbox();
info("Test setTilePositions uses sponsored_position value, not array index.");
let feed = getTopSitesFeedForTest(sandbox);
feed._telemetryUtility.setSponsoredTilesConfigured();
feed._telemetryUtility.setTiles([contileTile1, contileTile2, contileTile3]);
let filteredContileTiles = [
{
label: "brand1",
sponsored_position: 1,
partner: "amp",
},
{
label: "brand2",
sponsored_position: 2,
partner: "amp",
},
{
label: "brand3",
sponsored_position: 6,
partner: "amp",
},
];
feed._telemetryUtility.determineFilteredTilesAndSetToOversold(
filteredContileTiles
);
feed._telemetryUtility.finalizeNewtabPingFields(filteredContileTiles);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "brand1",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand2",
provider: "amp",
display_position: 2,
display_fail_reason: null,
},
{
advertiser: "brand3",
provider: "amp",
display_position: 6,
display_fail_reason: null,
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
sandbox.restore();
});
add_task(async function test_all_tiles_displayed() {
let sandbox = sinon.createSandbox();
info("if all provided tiles are displayed, the display_fail_reason is null");
let { feed, fetchStub } = prepFeed(getTopSitesFeedForTest(sandbox), sandbox);
fetchStub.resolves({
ok: true,
status: 200,
headers: new Map([
["cache-control", "private, max-age=859, stale-if-error=10463"],
]),
json: () =>
Promise.resolve({
tiles: [
{
image_url: "images/brand1-com.png",
name: "brand1",
},
{
image_url: "images/brand2-com.png",
name: "brand2",
},
],
}),
});
const fetched = await feed._contile._fetchSites();
Assert.ok(fetched);
Assert.equal(feed._contile.sites.length, 2);
await feed._readDefaults();
await feed.getLinksWithDefaults(false);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 2);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "brand1",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand2",
provider: "amp",
display_position: 2,
display_fail_reason: null,
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
sandbox.restore();
});
add_task(async function test_set_one_tile_display_fail_reason_to_oversold() {
let sandbox = sinon.createSandbox();
let { feed, fetchStub } = prepFeed(getTopSitesFeedForTest(sandbox), sandbox);
fetchStub.resolves({
ok: true,
status: 200,
headers: new Map([
["cache-control", "private, max-age=859, stale-if-error=10463"],
]),
json: () =>
Promise.resolve({
tiles: [
{
image_url: "images/brand1-com.png",
name: "brand1",
},
{
image_url: "images/brand2-com.png",
name: "brand2",
},
{
image_url: "images/brnad3-com.png",
name: "brand3",
},
],
}),
});
const fetched = await feed._contile._fetchSites();
Assert.ok(fetched);
Assert.equal(feed._contile.sites.length, 2);
await feed._readDefaults();
await feed.getLinksWithDefaults(false);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 2);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "brand1",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand2",
provider: "amp",
display_position: 2,
display_fail_reason: null,
},
{
advertiser: "brand3",
provider: "amp",
display_position: null,
display_fail_reason: "oversold",
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
sandbox.restore();
});
add_task(async function test_set_one_tile_display_fail_reason_to_dismissed() {
let sandbox = sinon.createSandbox();
let { feed, fetchStub } = prepFeed(getTopSitesFeedForTest(sandbox), sandbox);
fetchStub.resolves({
ok: true,
status: 200,
headers: new Map([
["cache-control", "private, max-age=859, stale-if-error=10463"],
]),
json: () =>
Promise.resolve({
tiles: [
{
url: "https://foo.com",
image_url: "images/foo.png",
impression_url: "https://www.foo-impression.com",
name: "foo",
},
{
image_url: "images/brnad2-com.png",
name: "brand2",
},
{
image_url: "images/brand3-com.png",
name: "brand3",
},
],
}),
});
Services.prefs.setStringPref(
TOP_SITES_BLOCKED_SPONSORS_PREF,
`["foo","bar"]`
);
const fetched = await feed._contile._fetchSites();
Assert.ok(fetched);
Assert.equal(feed._contile.sites.length, 2);
await feed._readDefaults();
await feed.getLinksWithDefaults(false);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 2);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "foo",
provider: "amp",
display_position: null,
display_fail_reason: "dismissed",
},
{
advertiser: "brand2",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand3",
provider: "amp",
display_position: 2,
display_fail_reason: null,
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
Services.prefs.clearUserPref(TOP_SITES_BLOCKED_SPONSORS_PREF);
sandbox.restore();
});
add_task(
async function test_set_one_tile_to_dismissed_and_one_tile_to_oversold() {
let sandbox = sinon.createSandbox();
let { feed, fetchStub } = prepFeed(
getTopSitesFeedForTest(sandbox),
sandbox
);
fetchStub.resolves({
ok: true,
status: 200,
headers: new Map([
["cache-control", "private, max-age=859, stale-if-error=10463"],
]),
json: () =>
Promise.resolve({
tiles: [
{
url: "https://foo.com",
image_url: "images/foo.png",
impression_url: "https://www.foo-impression.com",
name: "foo",
},
{
image_url: "images/brand2-com.png",
name: "brand2",
},
{
image_url: "images/brand3-com.png",
name: "brand3",
},
{
image_url: "images/brand4-com.png",
name: "brand4",
},
],
}),
});
Services.prefs.setStringPref(
TOP_SITES_BLOCKED_SPONSORS_PREF,
`["foo","bar"]`
);
const fetched = await feed._contile._fetchSites();
Assert.ok(fetched);
Assert.equal(feed._contile.sites.length, 2);
await feed._readDefaults();
await feed.getLinksWithDefaults(false);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 2);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "foo",
provider: "amp",
display_position: null,
display_fail_reason: "dismissed",
},
{
advertiser: "brand2",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand3",
provider: "amp",
display_position: 2,
display_fail_reason: null,
},
{
advertiser: "brand4",
provider: "amp",
display_position: null,
display_fail_reason: "oversold",
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
Services.prefs.clearUserPref(TOP_SITES_BLOCKED_SPONSORS_PREF);
sandbox.restore();
}
);
add_task(
async function test_set_one_cached_tile_display_fail_reason_to_dismissed() {
let sandbox = sinon.createSandbox();
info("confirm the telemetry is valid when using cached tiles.");
let { feed, fetchStub } = prepFeed(
getTopSitesFeedForTest(sandbox),
sandbox
);
const tiles = [
{
image_url: "images/brand1-com.png",
name: "brand1",
},
{
url: "https://foo.com",
image_url: "images/foo-com.png",
impression_url: "https://www.foo-impression.com",
name: "foo",
},
];
Services.prefs.setStringPref(CONTILE_CACHE_PREF, JSON.stringify(tiles));
Services.prefs.setIntPref(CONTILE_CACHE_VALID_FOR_PREF, 60 * 15);
Services.prefs.setIntPref(
CONTILE_CACHE_LAST_FETCH_PREF,
Math.round(Date.now() / 1000)
);
Services.prefs.setStringPref(
TOP_SITES_BLOCKED_SPONSORS_PREF,
`["foo","bar"]`
);
fetchStub.resolves({
status: 304,
});
const fetched = await feed._contile._fetchSites();
Assert.ok(fetched);
Assert.equal(feed._contile.sites.length, 1);
await feed._readDefaults();
await feed.getLinksWithDefaults(false);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 2);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "brand1",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "foo",
provider: "amp",
display_position: null,
display_fail_reason: "dismissed",
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
Services.prefs.clearUserPref(TOP_SITES_BLOCKED_SPONSORS_PREF);
sandbox.restore();
}
);
add_task(async function test_update_tile_count() {
let sandbox = sinon.createSandbox();
info(
"the tile count should update when topSitesMaxSponsored is updated by Nimbus"
);
let { feed, fetchStub } = prepFeed(getTopSitesFeedForTest(sandbox), sandbox);
fetchStub.resolves({
ok: true,
status: 200,
headers: new Map([
["cache-control", "private, max-age=859, stale-if-error=10463"],
]),
json: () =>
Promise.resolve({
tiles: [
{
image_url: "images/brand1-com.png",
name: "brand1",
},
{
image_url: "images/brand2-com.png",
name: "brand2",
},
{
image_url: "images/brand3-com.png",
name: "brand3",
},
],
}),
});
// 1. Initially the Nimbus pref is set to 2 tiles
let fetched = await feed._contile._fetchSites();
Assert.ok(fetched);
Assert.equal(feed._contile.sites.length, 2);
await feed._readDefaults();
await feed.getLinksWithDefaults(false);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 2);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "brand1",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand2",
provider: "amp",
display_position: 2,
display_fail_reason: null,
},
{
advertiser: "brand3",
provider: "amp",
display_position: null,
display_fail_reason: "oversold",
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
// 2. Set the Numbus pref to 3, confirm previous count still used.
const nimbusPocketStub = sandbox.stub(
NimbusFeatures.pocketNewtab,
"getVariable"
);
setNimbusVariablesForNumTiles(nimbusPocketStub, 3);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 2);
expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "brand1",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand2",
provider: "amp",
display_position: 2,
display_fail_reason: null,
},
{
advertiser: "brand3",
provider: "amp",
display_position: null,
display_fail_reason: "oversold",
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
// 3. Confirm the new count is applied when data pulled from Contile., 3 tiles displayed
fetched = await feed._contile._fetchSites();
Assert.ok(fetched);
Assert.equal(feed._contile.sites.length, 3);
await feed._readDefaults();
await feed.getLinksWithDefaults(false);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 3);
expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "brand1",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand2",
provider: "amp",
display_position: 2,
display_fail_reason: null,
},
{
advertiser: "brand3",
provider: "amp",
display_position: 3,
display_fail_reason: null,
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
sandbox.restore();
});
add_task(async function test_update_tile_count_sourced_from_cache() {
let sandbox = sinon.createSandbox();
info(
"the tile count should update from cache when topSitesMaxSponsored is updated by Nimbus"
);
let { feed, fetchStub } = prepFeed(getTopSitesFeedForTest(sandbox), sandbox);
const tiles = [
{
image_url: "images/brand1-com.png",
name: "brand1",
},
{
image_url: "images/brand2-com.png",
name: "brand2",
},
{
image_url: "images/brand3-com.png",
name: "brand3",
},
];
Services.prefs.setStringPref(CONTILE_CACHE_PREF, JSON.stringify(tiles));
Services.prefs.setIntPref(CONTILE_CACHE_VALID_FOR_PREF, 60 * 15);
Services.prefs.setIntPref(
CONTILE_CACHE_LAST_FETCH_PREF,
Math.round(Date.now() / 1000)
);
fetchStub.resolves({
status: 304,
});
// 1. Initially the Nimbus pref is set to 2 tiles
// Ensure ContileIntegration._fetchSites is working populate _sites and initilize TelemetryUtility
let fetched = await feed._contile._fetchSites();
Assert.ok(fetched);
Assert.equal(feed._contile.sites.length, 3);
await feed._readDefaults();
await feed.getLinksWithDefaults(false);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 2);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "brand1",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand2",
provider: "amp",
display_position: 2,
display_fail_reason: null,
},
{
advertiser: "brand3",
provider: "amp",
display_position: null,
display_fail_reason: "oversold",
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
// 2. Set the Numbus pref to 3, confirm previous count still used.
const nimbusPocketStub = sandbox.stub(
NimbusFeatures.pocketNewtab,
"getVariable"
);
setNimbusVariablesForNumTiles(nimbusPocketStub, 3);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 2);
// 3. Confirm the new count is applied when data pulled from Contile, 3 tiles displayed
fetched = await feed._contile._fetchSites();
Assert.ok(fetched);
Assert.equal(feed._contile.sites.length, 3);
await feed._readDefaults();
await feed.getLinksWithDefaults(false);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 3);
expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "brand1",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand2",
provider: "amp",
display_position: 2,
display_fail_reason: null,
},
{
advertiser: "brand3",
provider: "amp",
display_position: 3,
display_fail_reason: null,
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
sandbox.restore();
});
add_task(
async function test_update_telemetry_fields_if_dismissed_brands_list_is_updated() {
let sandbox = sinon.createSandbox();
info(
"if the user dismisses a brand, that dismissed tile shoudl be represented in the next ping."
);
let { feed, fetchStub } = prepFeed(
getTopSitesFeedForTest(sandbox),
sandbox
);
fetchStub.resolves({
ok: true,
status: 200,
headers: new Map([
["cache-control", "private, max-age=859, stale-if-error=10463"],
]),
json: () =>
Promise.resolve({
tiles: [
{
url: "https://foo.com",
image_url: "images/foo.png",
impression_url: "https://www.foo-impression.com",
name: "foo",
},
{
image_url: "images/brand2-com.png",
name: "brand2",
},
{
image_url: "images/brand3-com.png",
name: "brand3",
},
],
}),
});
Services.prefs.setStringPref(
TOP_SITES_BLOCKED_SPONSORS_PREF,
`["foo","bar"]`
);
let fetched = await feed._contile._fetchSites();
Assert.ok(fetched);
Assert.equal(feed._contile.sites.length, 2);
await feed._readDefaults();
await feed.getLinksWithDefaults(false);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 2);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "foo",
provider: "amp",
display_position: null,
display_fail_reason: "dismissed",
},
{
advertiser: "brand2",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand3",
provider: "amp",
display_position: 2,
display_fail_reason: null,
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
Services.prefs.setStringPref(
TOP_SITES_BLOCKED_SPONSORS_PREF,
`["foo","bar","brand2"]`
);
fetched = await feed._contile._fetchSites();
Assert.ok(fetched);
Assert.equal(feed._contile.sites.length, 1);
await feed._readDefaults();
await feed.getLinksWithDefaults(false);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 2);
expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "foo",
provider: "amp",
display_position: null,
display_fail_reason: "dismissed",
},
{
advertiser: "brand2",
provider: "amp",
display_position: null,
display_fail_reason: "dismissed",
},
{
advertiser: "brand3",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
Services.prefs.clearUserPref(TOP_SITES_BLOCKED_SPONSORS_PREF);
sandbox.restore();
}
);
add_task(async function test_sponsoredTilesReceived_not_set() {
let sandbox = sinon.createSandbox();
info("sponsoredTilesReceived should be empty if tiles service returns 204");
let { feed, fetchStub } = prepFeed(getTopSitesFeedForTest(sandbox), sandbox);
fetchStub.resolves({ ok: true, status: 204 });
const fetched = await feed._contile._fetchSites();
Assert.ok(!fetched);
Assert.ok(!feed._contile.sites.length);
await feed._readDefaults();
await feed.getLinksWithDefaults(false);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 2);
let expectedResult = { sponsoredTilesReceived: [] };
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
sandbox.restore();
});
add_task(async function test_telemetry_data_updates() {
let sandbox = sinon.createSandbox();
info("sponsoredTilesReceived should update when new tiles received.");
let { feed, fetchStub } = prepFeed(getTopSitesFeedForTest(sandbox), sandbox);
fetchStub.resolves({
ok: true,
status: 200,
headers: new Map([
["cache-control", "private, max-age=859, stale-if-error=10463"],
]),
json: () =>
Promise.resolve({
tiles: [
{
url: "https://foo.com",
image_url: "images/foo.png",
impression_url: "https://www.foo-impression.com",
name: "foo",
},
{
image_url: "images/brand2-com.png",
name: "brand2",
},
{
image_url: "images/brand3-com.png",
name: "brand3",
},
],
}),
});
Services.prefs.setStringPref(
TOP_SITES_BLOCKED_SPONSORS_PREF,
`["foo","bar"]`
);
const fetched = await feed._contile._fetchSites();
Assert.ok(fetched);
Assert.equal(feed._contile.sites.length, 2);
await feed._readDefaults();
await feed.getLinksWithDefaults(false);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 2);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "foo",
provider: "amp",
display_position: null,
display_fail_reason: "dismissed",
},
{
advertiser: "brand2",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand3",
provider: "amp",
display_position: 2,
display_fail_reason: null,
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
fetchStub.resolves({
ok: true,
status: 200,
headers: new Map([
["cache-control", "private, max-age=859, stale-if-error=10463"],
]),
json: () =>
Promise.resolve({
tiles: [
{
url: "https://foo.com",
image_url: "images/foo.png",
impression_url: "https://www.foo-impression.com",
name: "foo",
},
{
url: "https://bar.com",
image_url: "images/bar-com.png",
impression_url: "https://www.bar-impression.com",
name: "bar",
},
{
image_url: "images/brand3-com.png",
name: "brand3",
},
],
}),
});
await feed._contile._fetchSites();
Assert.ok(fetched);
Assert.equal(feed._contile.sites.length, 1);
await feed._readDefaults();
await feed.getLinksWithDefaults(false);
expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "foo",
provider: "amp",
display_position: null,
display_fail_reason: "dismissed",
},
{
advertiser: "bar",
provider: "amp",
display_position: null,
display_fail_reason: "dismissed",
},
{
advertiser: "brand3",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
Services.prefs.clearUserPref(TOP_SITES_BLOCKED_SPONSORS_PREF);
sandbox.restore();
});
add_task(async function test_reset_telemetry_data() {
let sandbox = sinon.createSandbox();
info(
"sponsoredTilesReceived should be cleared when no tiles received and cache refreshed."
);
let { feed, fetchStub } = prepFeed(getTopSitesFeedForTest(sandbox), sandbox);
fetchStub.resolves({
ok: true,
status: 200,
headers: new Map([
["cache-control", "private, max-age=859, stale-if-error=10463"],
]),
json: () =>
Promise.resolve({
tiles: [
{
url: "https://foo.com",
image_url: "images/foo.png",
impression_url: "https://www.foo-impression.com",
name: "foo",
},
{
image_url: "images/brand2-com.png",
name: "brand2",
},
{
image_url: "images/brand3-com.png",
name: "test3",
},
],
}),
});
Services.prefs.setStringPref(
TOP_SITES_BLOCKED_SPONSORS_PREF,
`["foo","bar"]`
);
let fetched = await feed._contile._fetchSites();
Assert.ok(fetched);
Assert.equal(feed._contile.sites.length, 2);
await feed._readDefaults();
await feed.getLinksWithDefaults(false);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 2);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "foo",
provider: "amp",
display_position: null,
display_fail_reason: "dismissed",
},
{
advertiser: "brand2",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand3",
provider: "amp",
display_position: 2,
display_fail_reason: null,
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
fetchStub.resolves({ ok: true, status: 204 });
fetched = await feed._contile._fetchSites();
Assert.ok(fetched);
Assert.ok(!feed._contile.sites.length);
await feed._readDefaults();
await feed.getLinksWithDefaults(false);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 2);
expectedResult = { sponsoredTilesReceived: [] };
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
Services.prefs.clearUserPref(TOP_SITES_BLOCKED_SPONSORS_PREF);
sandbox.restore();
});
add_task(async function test_set_telemetry_for_moz_sales_tiles() {
let sandbox = sinon.createSandbox();
let { feed, fetchStub } = prepFeed(getTopSitesFeedForTest(sandbox), sandbox);
sandbox.stub(feed, "fetchDiscoveryStreamSpocs").returns([
{
label: "MozSales Title",
title: "MozSales Title",
sponsored_position: 1,
partner: "moz-sales",
},
]);
fetchStub.resolves({
ok: true,
status: 200,
headers: new Map([
["cache-control", "private, max-age=859, stale-if-error=10463"],
]),
json: () =>
Promise.resolve({
tiles: [
{
image_url: "images/brand1-com.png",
name: "brand1",
},
{
image_url: "images/brand2-com.png",
name: "brand2",
},
],
}),
});
const fetched = await feed._contile._fetchSites();
Assert.ok(fetched);
Assert.equal(feed._contile.sites.length, 2);
await feed._readDefaults();
await feed.getLinksWithDefaults(false);
Assert.equal(Glean.topsites.sponsoredTilesConfigured.testGetValue(), 2);
let expectedResult = {
sponsoredTilesReceived: [
{
advertiser: "brand1",
provider: "amp",
display_position: 1,
display_fail_reason: null,
},
{
advertiser: "brand2",
provider: "amp",
display_position: 2,
display_fail_reason: null,
},
{
advertiser: "mozsales title",
provider: "moz-sales",
display_position: null,
display_fail_reason: "oversold",
},
],
};
Assert.equal(
Glean.topsites.sponsoredTilesReceived.testGetValue(),
JSON.stringify(expectedResult)
);
sandbox.restore();
});