зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1535460 - Add dark theme styles, Discovery stream blocking and bug fixes to Activity Stream r=r1cky
Differential Revision: https://phabricator.services.mozilla.com/D23589 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
2cf028fbc4
Коммит
bdcd004f99
|
@ -484,6 +484,34 @@ function DiscoveryStream(prevState = INITIAL_STATE.DiscoveryStream, action) {
|
|||
spocs_endpoint: action.data || INITIAL_STATE.DiscoveryStream.spocs.spocs_endpoint,
|
||||
},
|
||||
};
|
||||
case at.PLACES_LINK_BLOCKED:
|
||||
// Return if action data is empty, or spocs or feeds data is not loaded
|
||||
if (!action.data || !prevState.spocs.loaded || !prevState.feeds.loaded) {
|
||||
return prevState;
|
||||
}
|
||||
// Filter spocs and recommendations data inside feeds by removing action.data.url
|
||||
// received on PLACES_LINK_BLOCKED triggered by dismiss link menu option
|
||||
return {
|
||||
...prevState,
|
||||
spocs: {
|
||||
...prevState.spocs,
|
||||
data: prevState.spocs.data.spocs ? {
|
||||
spocs: prevState.spocs.data.spocs.filter(s => s.url !== action.data.url),
|
||||
} : {},
|
||||
},
|
||||
feeds: {
|
||||
...prevState.feeds,
|
||||
data: Object.keys(prevState.feeds.data).reduce((accumulator, feed_url) => {
|
||||
accumulator[feed_url] = {
|
||||
data: {
|
||||
...prevState.feeds.data[feed_url].data,
|
||||
recommendations: prevState.feeds.data[feed_url].data.recommendations.filter(r => r.url !== action.data.url),
|
||||
},
|
||||
};
|
||||
return accumulator;
|
||||
}, {}),
|
||||
},
|
||||
};
|
||||
case at.DISCOVERY_STREAM_SPOCS_UPDATE:
|
||||
if (action.data) {
|
||||
return {
|
||||
|
|
|
@ -60,7 +60,8 @@ export class DSCard extends React.PureComponent {
|
|||
source={this.props.type} />
|
||||
</SafeAnchor>
|
||||
<DSLinkMenu
|
||||
index={this.props.index}
|
||||
id={this.props.id}
|
||||
index={this.props.pos}
|
||||
dispatch={this.props.dispatch}
|
||||
intl={this.props.intl}
|
||||
url={this.props.url}
|
||||
|
|
|
@ -21,6 +21,10 @@ $excerpt-line-height: 20;
|
|||
|
||||
&:active {
|
||||
header {
|
||||
@include dark-theme-only {
|
||||
color: $blue-50;
|
||||
}
|
||||
|
||||
color: $blue-70;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,9 +42,9 @@ export class _DSLinkMenu extends React.PureComponent {
|
|||
render() {
|
||||
const {index, dispatch} = this.props;
|
||||
const isContextMenuOpen = this.state.showContextMenu && this.state.activeCard === index;
|
||||
const TOP_STORIES_SOURCE = "TOP_STORIES";
|
||||
const TOP_STORIES_CONTEXT_MENU_OPTIONS = ["OpenInNewWindow", "OpenInPrivateWindow"];
|
||||
const TOP_STORIES_CONTEXT_MENU_OPTIONS = ["OpenInNewWindow", "OpenInPrivateWindow", "Separator", "BlockUrl"];
|
||||
const title = this.props.title || this.props.source;
|
||||
const type = this.props.type || "DISCOVERY_STREAM";
|
||||
|
||||
return (<div>
|
||||
<button ref={this.contextMenuButtonRef}
|
||||
|
@ -59,15 +59,17 @@ export class _DSLinkMenu extends React.PureComponent {
|
|||
<LinkMenu
|
||||
dispatch={dispatch}
|
||||
index={index}
|
||||
source={TOP_STORIES_SOURCE}
|
||||
source={type.toUpperCase()}
|
||||
onUpdate={this.onMenuUpdate}
|
||||
onShow={this.onMenuShow}
|
||||
options={TOP_STORIES_CONTEXT_MENU_OPTIONS}
|
||||
shouldSendImpressionStats={true}
|
||||
site={{
|
||||
referrer: "https://getpocket.com/recommendations",
|
||||
title: this.props.title,
|
||||
type: this.props.type,
|
||||
url: this.props.url,
|
||||
guid: this.props.id,
|
||||
}} />
|
||||
}
|
||||
</div>);
|
||||
|
|
|
@ -32,7 +32,7 @@ export class Hero extends React.PureComponent {
|
|||
const {data} = this.props;
|
||||
|
||||
// Handle a render before feed has been fetched by displaying nothing
|
||||
if (!data || !data.recommendations) {
|
||||
if (!data || !data.recommendations || !data.recommendations.length) {
|
||||
return (
|
||||
<div />
|
||||
);
|
||||
|
@ -97,7 +97,8 @@ export class Hero extends React.PureComponent {
|
|||
source={this.props.type} />
|
||||
</SafeAnchor>
|
||||
<DSLinkMenu
|
||||
index={this.props.index}
|
||||
id={heroRec.id}
|
||||
index={heroRec.pos}
|
||||
dispatch={this.props.dispatch}
|
||||
intl={this.props.intl}
|
||||
url={heroRec.url}
|
||||
|
|
|
@ -172,6 +172,7 @@ $card-header-in-hero-line-height: 20;
|
|||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-column-gap: 24px;
|
||||
grid-auto-rows: min-content;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,6 +232,7 @@ $card-header-in-hero-line-height: 20;
|
|||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-column-gap: 24px;
|
||||
grid-auto-rows: min-content;
|
||||
|
||||
.ds-card {
|
||||
&:hover {
|
||||
|
|
|
@ -63,7 +63,8 @@ export class ListItem extends React.PureComponent {
|
|||
source={this.props.type} />
|
||||
</SafeAnchor>
|
||||
<DSLinkMenu
|
||||
index={this.props.index}
|
||||
id={this.props.id}
|
||||
index={this.props.pos}
|
||||
dispatch={this.props.dispatch}
|
||||
intl={this.props.intl}
|
||||
url={this.props.url}
|
||||
|
|
|
@ -2065,7 +2065,8 @@ main {
|
|||
.ds-column-8 .ds-hero .cards {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-column-gap: 24px; }
|
||||
grid-column-gap: 24px;
|
||||
grid-auto-rows: min-content; }
|
||||
.ds-column-9 .ds-hero,
|
||||
.ds-column-10 .ds-hero,
|
||||
.ds-column-11 .ds-hero,
|
||||
|
@ -2143,7 +2144,8 @@ main {
|
|||
.ds-column-12 .ds-hero .cards {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-column-gap: 24px; }
|
||||
grid-column-gap: 24px;
|
||||
grid-auto-rows: min-content; }
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .ds-column-9 .ds-hero .cards .ds-card:hover, [lwt-newtab-brighttext]:not(.force-light-theme)
|
||||
.ds-column-10 .ds-hero .cards .ds-card:hover, [lwt-newtab-brighttext]:not(.force-light-theme)
|
||||
.ds-column-11 .ds-hero .cards .ds-card:hover, [lwt-newtab-brighttext]:not(.force-light-theme)
|
||||
|
@ -2560,6 +2562,8 @@ main {
|
|||
color: #45A1FF; }
|
||||
.ds-card:active header {
|
||||
color: #003EAA; }
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .ds-card:active header {
|
||||
color: #0A84FF; }
|
||||
.ds-card .img-wrapper {
|
||||
width: 100%; }
|
||||
.ds-card .img {
|
||||
|
|
|
@ -2068,7 +2068,8 @@ main {
|
|||
.ds-column-8 .ds-hero .cards {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-column-gap: 24px; }
|
||||
grid-column-gap: 24px;
|
||||
grid-auto-rows: min-content; }
|
||||
.ds-column-9 .ds-hero,
|
||||
.ds-column-10 .ds-hero,
|
||||
.ds-column-11 .ds-hero,
|
||||
|
@ -2146,7 +2147,8 @@ main {
|
|||
.ds-column-12 .ds-hero .cards {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-column-gap: 24px; }
|
||||
grid-column-gap: 24px;
|
||||
grid-auto-rows: min-content; }
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .ds-column-9 .ds-hero .cards .ds-card:hover, [lwt-newtab-brighttext]:not(.force-light-theme)
|
||||
.ds-column-10 .ds-hero .cards .ds-card:hover, [lwt-newtab-brighttext]:not(.force-light-theme)
|
||||
.ds-column-11 .ds-hero .cards .ds-card:hover, [lwt-newtab-brighttext]:not(.force-light-theme)
|
||||
|
@ -2563,6 +2565,8 @@ main {
|
|||
color: #45A1FF; }
|
||||
.ds-card:active header {
|
||||
color: #003EAA; }
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .ds-card:active header {
|
||||
color: #0A84FF; }
|
||||
.ds-card .img-wrapper {
|
||||
width: 100%; }
|
||||
.ds-card .img {
|
||||
|
|
|
@ -2065,7 +2065,8 @@ main {
|
|||
.ds-column-8 .ds-hero .cards {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-column-gap: 24px; }
|
||||
grid-column-gap: 24px;
|
||||
grid-auto-rows: min-content; }
|
||||
.ds-column-9 .ds-hero,
|
||||
.ds-column-10 .ds-hero,
|
||||
.ds-column-11 .ds-hero,
|
||||
|
@ -2143,7 +2144,8 @@ main {
|
|||
.ds-column-12 .ds-hero .cards {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-column-gap: 24px; }
|
||||
grid-column-gap: 24px;
|
||||
grid-auto-rows: min-content; }
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .ds-column-9 .ds-hero .cards .ds-card:hover, [lwt-newtab-brighttext]:not(.force-light-theme)
|
||||
.ds-column-10 .ds-hero .cards .ds-card:hover, [lwt-newtab-brighttext]:not(.force-light-theme)
|
||||
.ds-column-11 .ds-hero .cards .ds-card:hover, [lwt-newtab-brighttext]:not(.force-light-theme)
|
||||
|
@ -2560,6 +2562,8 @@ main {
|
|||
color: #45A1FF; }
|
||||
.ds-card:active header {
|
||||
color: #003EAA; }
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .ds-card:active header {
|
||||
color: #0A84FF; }
|
||||
.ds-card .img-wrapper {
|
||||
width: 100%; }
|
||||
.ds-card .img {
|
||||
|
|
|
@ -7296,9 +7296,9 @@ class DSLinkMenu_DSLinkMenu extends external_React_default.a.PureComponent {
|
|||
render() {
|
||||
const { index, dispatch } = this.props;
|
||||
const isContextMenuOpen = this.state.showContextMenu && this.state.activeCard === index;
|
||||
const TOP_STORIES_SOURCE = "TOP_STORIES";
|
||||
const TOP_STORIES_CONTEXT_MENU_OPTIONS = ["OpenInNewWindow", "OpenInPrivateWindow"];
|
||||
const TOP_STORIES_CONTEXT_MENU_OPTIONS = ["OpenInNewWindow", "OpenInPrivateWindow", "Separator", "BlockUrl"];
|
||||
const title = this.props.title || this.props.source;
|
||||
const type = this.props.type || "DISCOVERY_STREAM";
|
||||
|
||||
return external_React_default.a.createElement(
|
||||
"div",
|
||||
|
@ -7318,15 +7318,17 @@ class DSLinkMenu_DSLinkMenu extends external_React_default.a.PureComponent {
|
|||
isContextMenuOpen && external_React_default.a.createElement(LinkMenu["LinkMenu"], {
|
||||
dispatch: dispatch,
|
||||
index: index,
|
||||
source: TOP_STORIES_SOURCE,
|
||||
source: type.toUpperCase(),
|
||||
onUpdate: this.onMenuUpdate,
|
||||
onShow: this.onMenuShow,
|
||||
options: TOP_STORIES_CONTEXT_MENU_OPTIONS,
|
||||
shouldSendImpressionStats: true,
|
||||
site: {
|
||||
referrer: "https://getpocket.com/recommendations",
|
||||
title: this.props.title,
|
||||
type: this.props.type,
|
||||
url: this.props.url
|
||||
url: this.props.url,
|
||||
guid: this.props.id
|
||||
} })
|
||||
);
|
||||
}
|
||||
|
@ -7483,7 +7485,8 @@ class DSCard_DSCard extends external_React_default.a.PureComponent {
|
|||
source: this.props.type })
|
||||
),
|
||||
external_React_default.a.createElement(DSLinkMenu, {
|
||||
index: this.props.index,
|
||||
id: this.props.id,
|
||||
index: this.props.pos,
|
||||
dispatch: this.props.dispatch,
|
||||
intl: this.props.intl,
|
||||
url: this.props.url,
|
||||
|
@ -7670,7 +7673,8 @@ class List_ListItem extends external_React_default.a.PureComponent {
|
|||
source: this.props.type })
|
||||
),
|
||||
external_React_default.a.createElement(DSLinkMenu, {
|
||||
index: this.props.index,
|
||||
id: this.props.id,
|
||||
index: this.props.pos,
|
||||
dispatch: this.props.dispatch,
|
||||
intl: this.props.intl,
|
||||
url: this.props.url,
|
||||
|
@ -7764,7 +7768,7 @@ class Hero_Hero extends external_React_default.a.PureComponent {
|
|||
const { data } = this.props;
|
||||
|
||||
// Handle a render before feed has been fetched by displaying nothing
|
||||
if (!data || !data.recommendations) {
|
||||
if (!data || !data.recommendations || !data.recommendations.length) {
|
||||
return external_React_default.a.createElement("div", null);
|
||||
}
|
||||
|
||||
|
@ -7852,7 +7856,8 @@ class Hero_Hero extends external_React_default.a.PureComponent {
|
|||
source: this.props.type })
|
||||
),
|
||||
external_React_default.a.createElement(DSLinkMenu, {
|
||||
index: this.props.index,
|
||||
id: heroRec.id,
|
||||
index: heroRec.pos,
|
||||
dispatch: this.props.dispatch,
|
||||
intl: this.props.intl,
|
||||
url: heroRec.url,
|
||||
|
@ -12357,6 +12362,30 @@ function DiscoveryStream(prevState = INITIAL_STATE.DiscoveryStream, action) {
|
|||
spocs_endpoint: action.data || INITIAL_STATE.DiscoveryStream.spocs.spocs_endpoint
|
||||
})
|
||||
});
|
||||
case Actions["actionTypes"].PLACES_LINK_BLOCKED:
|
||||
// Return if action data is empty, or spocs or feeds data is not loaded
|
||||
if (!action.data || !prevState.spocs.loaded || !prevState.feeds.loaded) {
|
||||
return prevState;
|
||||
}
|
||||
// Filter spocs and recommendations data inside feeds by removing action.data.url
|
||||
// received on PLACES_LINK_BLOCKED triggered by dismiss link menu option
|
||||
return Object.assign({}, prevState, {
|
||||
spocs: Object.assign({}, prevState.spocs, {
|
||||
data: prevState.spocs.data.spocs ? {
|
||||
spocs: prevState.spocs.data.spocs.filter(s => s.url !== action.data.url)
|
||||
} : {}
|
||||
}),
|
||||
feeds: Object.assign({}, prevState.feeds, {
|
||||
data: Object.keys(prevState.feeds.data).reduce((accumulator, feed_url) => {
|
||||
accumulator[feed_url] = {
|
||||
data: Object.assign({}, prevState.feeds.data[feed_url].data, {
|
||||
recommendations: prevState.feeds.data[feed_url].data.recommendations.filter(r => r.url !== action.data.url)
|
||||
})
|
||||
};
|
||||
return accumulator;
|
||||
}, {})
|
||||
})
|
||||
});
|
||||
case Actions["actionTypes"].DISCOVERY_STREAM_SPOCS_UPDATE:
|
||||
if (action.data) {
|
||||
return Object.assign({}, prevState, {
|
||||
|
|
|
@ -243,6 +243,10 @@ const PREFS_CONFIG = new Map([
|
|||
});
|
||||
},
|
||||
}],
|
||||
["discoverystream.endpoints", {
|
||||
title: "Endpoint prefixes (comma-separated) that are allowed to be requested",
|
||||
value: "https://getpocket.cdn.mozilla.net/",
|
||||
}],
|
||||
["discoverystream.optOut.0", {
|
||||
title: "Opt out of new layout v0",
|
||||
value: false,
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
"use strict";
|
||||
|
||||
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
const {NewTabUtils} = ChromeUtils.import("resource://gre/modules/NewTabUtils.jsm");
|
||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]);
|
||||
ChromeUtils.defineModuleGetter(this, "perfService", "resource://activity-stream/common/PerfService.jsm");
|
||||
|
@ -19,6 +20,7 @@ const SPOCS_FEEDS_UPDATE_TIME = 30 * 60 * 1000; // 30 minutes
|
|||
const DEFAULT_RECS_EXPIRE_TIME = 60 * 60 * 1000; // 1 hour
|
||||
const MAX_LIFETIME_CAP = 500; // Guard against misconfiguration on the server
|
||||
const PREF_CONFIG = "discoverystream.config";
|
||||
const PREF_ENDPOINTS = "discoverystream.endpoints";
|
||||
const PREF_OPT_OUT = "discoverystream.optOut.0";
|
||||
const PREF_SHOW_SPONSORED = "showSponsored";
|
||||
const PREF_SPOC_IMPRESSIONS = "discoverystream.spoc.impressions";
|
||||
|
@ -88,17 +90,20 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
|
|||
return null;
|
||||
}
|
||||
try {
|
||||
// Make sure the requested endpoint is allowed
|
||||
const allowed = this.store.getState().Prefs.values[PREF_ENDPOINTS].split(",");
|
||||
if (!allowed.some(prefix => endpoint.startsWith(prefix))) {
|
||||
throw new Error(`Not one of allowed prefixes (${allowed})`);
|
||||
}
|
||||
|
||||
const response = await fetch(endpoint, {credentials: "omit"});
|
||||
if (!response.ok) {
|
||||
// istanbul ignore next
|
||||
throw new Error(`${endpoint} returned unexpected status: ${response.status}`);
|
||||
throw new Error(`Unexpected status (${response.status})`);
|
||||
}
|
||||
return response.json();
|
||||
} catch (error) {
|
||||
// istanbul ignore next
|
||||
Cu.reportError(`Failed to fetch ${endpoint}: ${error.message}`);
|
||||
}
|
||||
// istanbul ignore next
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -200,11 +205,9 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
|
|||
// We initially stub this out so we don't fetch dupes,
|
||||
// we then fill in with the proper object inside the promise.
|
||||
newFeeds[url] = {};
|
||||
|
||||
const feedPromise = this.getComponentFeed(url, isStartup);
|
||||
|
||||
feedPromise.then(data => {
|
||||
newFeeds[url] = data;
|
||||
feedPromise.then(feed => {
|
||||
newFeeds[url] = this.filterRecommendations(feed);
|
||||
}).catch(/* istanbul ignore next */ error => {
|
||||
Cu.reportError(`Error trying to load component feed ${url}: ${error}`);
|
||||
});
|
||||
|
@ -214,6 +217,13 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
|
|||
};
|
||||
}
|
||||
|
||||
filterRecommendations(feed) {
|
||||
if (feed && feed.data && feed.data.recommendations && feed.data.recommendations.length) {
|
||||
return {data: this.filterBlocked(feed.data, "recommendations")};
|
||||
}
|
||||
return feed;
|
||||
}
|
||||
|
||||
/**
|
||||
* reduceFeedComponents - Filters out components with no feeds, and combines
|
||||
* all feeds on this component with the feeds from other components.
|
||||
|
@ -309,12 +319,24 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
|
|||
type: at.DISCOVERY_STREAM_SPOCS_UPDATE,
|
||||
data: {
|
||||
lastUpdated: spocs.lastUpdated,
|
||||
spocs: this.transform(this.filterSpocs(spocs.data)),
|
||||
spocs: this.transform(this.frequencyCapSpocs(spocs.data)),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
transform(data) {
|
||||
filterBlocked(data, type) {
|
||||
if (data && data[type] && data[type].length) {
|
||||
const filteredItems = data[type].filter(item => !NewTabUtils.blockedLinks.isBlocked({"url": item.url}));
|
||||
return {
|
||||
...data,
|
||||
[type]: filteredItems,
|
||||
};
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
transform(spocs) {
|
||||
const data = this.filterBlocked(spocs, "spocs");
|
||||
if (data && data.spocs && data.spocs.length) {
|
||||
const spocsPerDomain = this.store.getState().DiscoveryStream.spocs.spocs_per_domain || 1;
|
||||
const campaignMap = {};
|
||||
|
@ -340,7 +362,7 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
|
|||
}
|
||||
|
||||
// Filter spocs based on frequency caps
|
||||
filterSpocs(data) {
|
||||
frequencyCapSpocs(data) {
|
||||
if (data && data.spocs && data.spocs.length) {
|
||||
const {spocs} = data;
|
||||
const impressions = this.readImpressionsPref(PREF_SPOC_IMPRESSIONS);
|
||||
|
@ -711,7 +733,7 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
|
|||
type: at.DISCOVERY_STREAM_SPOCS_UPDATE,
|
||||
data: {
|
||||
lastUpdated: spocs.lastUpdated,
|
||||
spocs: this.transform(this.filterSpocs(spocs.data)),
|
||||
spocs: this.transform(this.frequencyCapSpocs(spocs.data)),
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -93,6 +93,8 @@ prefs_home_header=Konten Beranda Firefox
|
|||
prefs_home_description=Pilih konten yang ingin Anda tampilkan dalam Beranda Firefox.
|
||||
|
||||
prefs_content_discovery_header=Beranda Firefox
|
||||
prefs_content_discovery_description=Penemuan Konten dalam Firefox Home memungkinkan Anda untuk menemukan artikel bermutu tinggi dan relevan dari seluruh web.
|
||||
prefs_content_discovery_button=Matikan Penemuan Konten
|
||||
|
||||
# LOCALIZATION NOTE (prefs_section_rows_option): This is a semi-colon list of
|
||||
# plural forms used in a drop down of multiple row options (1 row, 2 rows).
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
newtab_page_title=Neuvo Feuggio
|
||||
newtab_page_title=Neuvo feuggio
|
||||
|
||||
header_top_sites=I megio sciti
|
||||
header_highlights=In evidensa
|
||||
|
@ -52,8 +52,8 @@ menu_action_archive_pocket=Archivia in Pocket
|
|||
menu_action_show_file_mac_os=Fanni vedde in Finder
|
||||
menu_action_show_file_windows=Arvi cartella
|
||||
menu_action_show_file_linux=Arvi cartella
|
||||
menu_action_show_file_default=Fanni vedde file
|
||||
menu_action_open_file=Arvi file
|
||||
menu_action_show_file_default=Mostra o schedaio
|
||||
menu_action_open_file=Arvi schedaio
|
||||
|
||||
# LOCALIZATION NOTE (menu_action_copy_download_link, menu_action_go_to_download_page):
|
||||
# "Download" here, in both cases, is not a verb, it is a noun. As in, "Copy the
|
||||
|
@ -93,6 +93,7 @@ prefs_home_header=Pagina iniçiâ de Firefox
|
|||
prefs_home_description=Çerni i contegnui che ti veu vedde inta pagina iniçiâ de Firefox.
|
||||
|
||||
prefs_content_discovery_header=Pagina iniçiâ de Firefox
|
||||
prefs_content_discovery_button=Dizabilita a descoverta de neuvi contegnui
|
||||
|
||||
# LOCALIZATION NOTE (prefs_section_rows_option): This is a semi-colon list of
|
||||
# plural forms used in a drop down of multiple row options (1 row, 2 rows).
|
||||
|
|
|
@ -132,14 +132,14 @@ topsites_form_title_label=Título
|
|||
topsites_form_title_placeholder=Digite um título
|
||||
topsites_form_url_label=URL
|
||||
topsites_form_image_url_label=URL de imagem personalizada
|
||||
topsites_form_url_placeholder=Digite ou cole um URL
|
||||
topsites_form_url_placeholder=Digite ou cole uma URL
|
||||
topsites_form_use_image_link=Usar uma imagem personalizada…
|
||||
# LOCALIZATION NOTE (topsites_form_*_button): These are verbs/actions.
|
||||
topsites_form_preview_button=Visualizar
|
||||
topsites_form_add_button=Adicionar
|
||||
topsites_form_save_button=Salvar
|
||||
topsites_form_cancel_button=Cancelar
|
||||
topsites_form_url_validation=É necessário um URL válido
|
||||
topsites_form_url_validation=É necessário uma URL válida
|
||||
topsites_form_image_validation=Não foi possível carregar a imagem. Tente uma URL diferente.
|
||||
|
||||
# LOCALIZATION NOTE (pocket_read_more): This is shown at the bottom of the
|
||||
|
|
|
@ -41,8 +41,8 @@ window.gActivityStreamStrings = {
|
|||
"prefs_home_header": "Konten Beranda Firefox",
|
||||
"prefs_home_description": "Pilih konten yang ingin Anda tampilkan dalam Beranda Firefox.",
|
||||
"prefs_content_discovery_header": "Beranda Firefox",
|
||||
"prefs_content_discovery_description": "Content Discovery in Firefox Home allows you to discover high-quality, relevant articles from across the web.",
|
||||
"prefs_content_discovery_button": "Turn Off Content Discovery",
|
||||
"prefs_content_discovery_description": "Penemuan Konten dalam Firefox Home memungkinkan Anda untuk menemukan artikel bermutu tinggi dan relevan dari seluruh web.",
|
||||
"prefs_content_discovery_button": "Matikan Penemuan Konten",
|
||||
"prefs_section_rows_option": "{num} baris",
|
||||
"prefs_search_header": "Pencarian Web",
|
||||
"prefs_topsites_description": "Situs yang sering Anda kunjungi",
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'unsafe-inline' resource: chrome:; connect-src https:; img-src https: data: blob:; style-src 'unsafe-inline';">
|
||||
<title>Neuvo Feuggio</title>
|
||||
<title>Neuvo feuggio</title>
|
||||
<link rel="icon" type="image/png" href="chrome://branding/content/icon32.png"/>
|
||||
<link rel="stylesheet" href="chrome://browser/content/contentSearchUI.css" />
|
||||
<link rel="stylesheet" href="resource://activity-stream/css/activity-stream.css" />
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'unsafe-inline' resource: chrome:; connect-src https:; img-src https: data: blob:; style-src 'unsafe-inline';">
|
||||
<title>Neuvo Feuggio</title>
|
||||
<title>Neuvo feuggio</title>
|
||||
<link rel="icon" type="image/png" href="chrome://branding/content/icon32.png"/>
|
||||
<link rel="stylesheet" href="chrome://browser/content/contentSearchUI.css" />
|
||||
<link rel="stylesheet" href="resource://activity-stream/css/activity-stream.css" />
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'unsafe-inline' resource: chrome:; connect-src https:; img-src https: data: blob:; style-src 'unsafe-inline';">
|
||||
<title>Neuvo Feuggio</title>
|
||||
<title>Neuvo feuggio</title>
|
||||
<link rel="icon" type="image/png" href="chrome://branding/content/icon32.png"/>
|
||||
<link rel="stylesheet" href="chrome://browser/content/contentSearchUI.css" />
|
||||
<link rel="stylesheet" href="resource://activity-stream/css/activity-stream.css" />
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Note - this is a generated lij file.
|
||||
window.gActivityStreamStrings = {
|
||||
"newtab_page_title": "Neuvo Feuggio",
|
||||
"newtab_page_title": "Neuvo feuggio",
|
||||
"header_top_sites": "I megio sciti",
|
||||
"header_highlights": "In evidensa",
|
||||
"header_recommended_by": "Consegiou da {provider}",
|
||||
|
@ -27,8 +27,8 @@ window.gActivityStreamStrings = {
|
|||
"menu_action_show_file_mac_os": "Fanni vedde in Finder",
|
||||
"menu_action_show_file_windows": "Arvi cartella",
|
||||
"menu_action_show_file_linux": "Arvi cartella",
|
||||
"menu_action_show_file_default": "Fanni vedde file",
|
||||
"menu_action_open_file": "Arvi file",
|
||||
"menu_action_show_file_default": "Mostra o schedaio",
|
||||
"menu_action_open_file": "Arvi schedaio",
|
||||
"menu_action_copy_download_link": "Còpia indirisso òrigine",
|
||||
"menu_action_go_to_download_page": "Vanni a-a pagina de descaregamento",
|
||||
"menu_action_remove_download": "Scancella da-a stöia",
|
||||
|
@ -42,7 +42,7 @@ window.gActivityStreamStrings = {
|
|||
"prefs_home_description": "Çerni i contegnui che ti veu vedde inta pagina iniçiâ de Firefox.",
|
||||
"prefs_content_discovery_header": "Pagina iniçiâ de Firefox",
|
||||
"prefs_content_discovery_description": "Content Discovery in Firefox Home allows you to discover high-quality, relevant articles from across the web.",
|
||||
"prefs_content_discovery_button": "Turn Off Content Discovery",
|
||||
"prefs_content_discovery_button": "Dizabilita a descoverta de neuvi contegnui",
|
||||
"prefs_section_rows_option": "{num} riga;{num} righe",
|
||||
"prefs_search_header": "Çerca into Web",
|
||||
"prefs_topsites_description": "I sciti che ti vixiti de ciù",
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'unsafe-inline' resource: chrome:; connect-src https:; img-src https: data: blob:; style-src 'unsafe-inline';">
|
||||
<title>Neuvo Feuggio</title>
|
||||
<title>Neuvo feuggio</title>
|
||||
<link rel="icon" type="image/png" href="chrome://branding/content/icon32.png"/>
|
||||
<link rel="stylesheet" href="chrome://browser/content/contentSearchUI.css" />
|
||||
<link rel="stylesheet" href="resource://activity-stream/css/activity-stream.css" />
|
||||
|
|
|
@ -67,13 +67,13 @@ window.gActivityStreamStrings = {
|
|||
"topsites_form_title_placeholder": "Digite um título",
|
||||
"topsites_form_url_label": "URL",
|
||||
"topsites_form_image_url_label": "URL de imagem personalizada",
|
||||
"topsites_form_url_placeholder": "Digite ou cole um URL",
|
||||
"topsites_form_url_placeholder": "Digite ou cole uma URL",
|
||||
"topsites_form_use_image_link": "Usar uma imagem personalizada…",
|
||||
"topsites_form_preview_button": "Visualizar",
|
||||
"topsites_form_add_button": "Adicionar",
|
||||
"topsites_form_save_button": "Salvar",
|
||||
"topsites_form_cancel_button": "Cancelar",
|
||||
"topsites_form_url_validation": "É necessário um URL válido",
|
||||
"topsites_form_url_validation": "É necessário uma URL válida",
|
||||
"topsites_form_image_validation": "Não foi possível carregar a imagem. Tente uma URL diferente.",
|
||||
"pocket_read_more": "Tópicos populares:",
|
||||
"pocket_read_even_more": "Ver mais histórias",
|
||||
|
|
|
@ -5,6 +5,7 @@ support-files =
|
|||
head.js
|
||||
prefs =
|
||||
browser.newtabpage.activity-stream.debug=false
|
||||
browser.newtabpage.activity-stream.discoverystream.endpoints=data:
|
||||
|
||||
[browser_activity_stream_strings.js]
|
||||
[browser_as_load_location.js]
|
||||
|
|
|
@ -31,6 +31,7 @@ describe("CFRPageActions", () => {
|
|||
"cfr-notification-footer-learn-more-link",
|
||||
"cfr-notification-footer-pintab-animation-container",
|
||||
"cfr-notification-footer-animation-button",
|
||||
"cfr-notification-footer-animation-label",
|
||||
];
|
||||
const elementClassNames = [
|
||||
"popup-notification-body-container",
|
||||
|
|
|
@ -702,6 +702,104 @@ describe("Reducers", () => {
|
|||
const state = DiscoveryStream(undefined, {type: at.DISCOVERY_STREAM_SPOCS_UPDATE, data});
|
||||
assert.deepEqual(state.spocs, INITIAL_STATE.DiscoveryStream.spocs);
|
||||
});
|
||||
it("should not update state for empty action.data on PLACES_LINK_BLOCKED", () => {
|
||||
const newState = DiscoveryStream(undefined, {type: at.PLACES_LINK_BLOCKED});
|
||||
assert.equal(newState, INITIAL_STATE.DiscoveryStream);
|
||||
});
|
||||
it("should not update state if feeds are not loaded", () => {
|
||||
const deleteAction = {type: at.PLACES_LINK_BLOCKED, data: {url: "foo.com"}};
|
||||
const newState = DiscoveryStream(undefined, deleteAction);
|
||||
assert.equal(newState, INITIAL_STATE.DiscoveryStream);
|
||||
});
|
||||
it("should not update state if spocs and feeds data is undefined", () => {
|
||||
const deleteAction = {type: at.PLACES_LINK_BLOCKED, data: {url: "foo.com"}};
|
||||
const oldState = {
|
||||
spocs: {
|
||||
data: {},
|
||||
loaded: true,
|
||||
},
|
||||
feeds: {
|
||||
data: {},
|
||||
loaded: true,
|
||||
},
|
||||
};
|
||||
const newState = DiscoveryStream(oldState, deleteAction);
|
||||
assert.deepEqual(newState, oldState);
|
||||
});
|
||||
it("should remove the site on PLACES_LINK_BLOCKED from spocs if feeds data is empty", () => {
|
||||
const deleteAction = {type: at.PLACES_LINK_BLOCKED, data: {url: "https://foo.com"}};
|
||||
const oldState = {
|
||||
spocs: {
|
||||
data: {
|
||||
spocs: [
|
||||
{url: "https://foo.com"},
|
||||
{url: "test-spoc.com"},
|
||||
],
|
||||
},
|
||||
loaded: true,
|
||||
},
|
||||
feeds: {
|
||||
data: {},
|
||||
loaded: true,
|
||||
},
|
||||
};
|
||||
const newState = DiscoveryStream(oldState, deleteAction);
|
||||
assert.deepEqual(newState.spocs.data.spocs, [{url: "test-spoc.com"}]);
|
||||
});
|
||||
it("should remove the site on PLACES_LINK_BLOCKED from feeds if spocs data is empty", () => {
|
||||
const deleteAction = {type: at.PLACES_LINK_BLOCKED, data: {url: "https://foo.com"}};
|
||||
const oldState = {
|
||||
spocs: {
|
||||
data: {},
|
||||
loaded: true,
|
||||
},
|
||||
feeds: {
|
||||
data: {
|
||||
"https://foo.com/feed1": {
|
||||
data: {
|
||||
recommendations: [
|
||||
{url: "https://foo.com"},
|
||||
{url: "test.com"},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
loaded: true,
|
||||
},
|
||||
};
|
||||
const newState = DiscoveryStream(oldState, deleteAction);
|
||||
assert.deepEqual(newState.feeds.data["https://foo.com/feed1"].data.recommendations, [{url: "test.com"}]);
|
||||
});
|
||||
it("should remove the site on PLACES_LINK_BLOCKED from both feeds and spocs", () => {
|
||||
const oldState = {
|
||||
feeds: {
|
||||
data: {
|
||||
"https://foo.com/feed1": {
|
||||
data: {
|
||||
recommendations: [
|
||||
{url: "https://foo.com"},
|
||||
{url: "test.com"},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
loaded: true,
|
||||
},
|
||||
spocs: {
|
||||
data: {
|
||||
spocs: [
|
||||
{url: "https://foo.com"},
|
||||
{url: "test-spoc.com"},
|
||||
],
|
||||
},
|
||||
loaded: true,
|
||||
},
|
||||
};
|
||||
const deleteAction = {type: at.PLACES_LINK_BLOCKED, data: {url: "https://foo.com"}};
|
||||
const newState = DiscoveryStream(oldState, deleteAction);
|
||||
assert.deepEqual(newState.spocs.data.spocs, [{url: "test-spoc.com"}]);
|
||||
assert.deepEqual(newState.feeds.data["https://foo.com/feed1"].data.recommendations, [{url: "test.com"}]);
|
||||
});
|
||||
});
|
||||
describe("Search", () => {
|
||||
it("should return INITIAL_STATE by default", () => {
|
||||
|
|
|
@ -24,16 +24,16 @@ describe("<DSLinkMenu>", () => {
|
|||
assert.equal(wrapper.find(LinkMenu).length, 1);
|
||||
});
|
||||
|
||||
it("should pass dispatch, onUpdate, onShow, site, options, source and index to LinkMenu", () => {
|
||||
it("should pass dispatch, onUpdate, onShow, site, options, shouldSendImpressionStats, source and index to LinkMenu", () => {
|
||||
wrapper.find(".context-menu-button").simulate("click", {preventDefault: () => {}});
|
||||
const linkMenuProps = wrapper.find(LinkMenu).props();
|
||||
["dispatch", "onUpdate", "onShow", "site", "index", "options", "source"].forEach(prop => assert.property(linkMenuProps, prop));
|
||||
["dispatch", "onUpdate", "onShow", "site", "index", "options", "source", "shouldSendImpressionStats"].forEach(prop => assert.property(linkMenuProps, prop));
|
||||
});
|
||||
|
||||
it("should pass through the correct menu options to LinkMenu", () => {
|
||||
wrapper.find(".context-menu-button").simulate("click", {preventDefault: () => {}});
|
||||
const linkMenuProps = wrapper.find(LinkMenu).props();
|
||||
assert.deepEqual(linkMenuProps.options,
|
||||
["OpenInNewWindow", "OpenInPrivateWindow"]);
|
||||
["OpenInNewWindow", "OpenInPrivateWindow", "Separator", "BlockUrl"]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import {actionCreators as ac, actionTypes as at, actionUtils as au} from "common/Actions.jsm";
|
||||
import {combineReducers, createStore} from "redux";
|
||||
import {DiscoveryStreamFeed} from "lib/DiscoveryStreamFeed.jsm";
|
||||
import {GlobalOverrider} from "test/unit/utils";
|
||||
import {reducers} from "common/Reducers.jsm";
|
||||
|
||||
const CONFIG_PREF_NAME = "discoverystream.config";
|
||||
const DUMMY_ENDPOINT = "https://getpocket.cdn.mozilla.net/dummy";
|
||||
const ENDPOINTS_PREF_NAME = "discoverystream.endpoints";
|
||||
const SPOC_IMPRESSION_TRACKING_PREF = "discoverystream.spoc.impressions";
|
||||
const REC_IMPRESSION_TRACKING_PREF = "discoverystream.rec.impressions";
|
||||
const THIRTY_MINUTES = 30 * 60 * 1000;
|
||||
|
@ -14,6 +17,9 @@ describe("DiscoveryStreamFeed", () => {
|
|||
let sandbox;
|
||||
let fetchStub;
|
||||
let clock;
|
||||
let fakeNewTabUtils;
|
||||
let globals;
|
||||
|
||||
const setPref = (name, value) => {
|
||||
const action = {
|
||||
type: at.PREF_CHANGED,
|
||||
|
@ -40,17 +46,72 @@ describe("DiscoveryStreamFeed", () => {
|
|||
feed.store = createStore(combineReducers(reducers), {
|
||||
Prefs: {
|
||||
values: {
|
||||
[CONFIG_PREF_NAME]: JSON.stringify({enabled: false, show_spocs: false, layout_endpoint: "foo"}),
|
||||
[CONFIG_PREF_NAME]: JSON.stringify({enabled: false, show_spocs: false, layout_endpoint: DUMMY_ENDPOINT}),
|
||||
[ENDPOINTS_PREF_NAME]: DUMMY_ENDPOINT,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
sandbox.stub(feed, "_maybeUpdateCachedData").resolves();
|
||||
|
||||
globals = new GlobalOverrider();
|
||||
fakeNewTabUtils = {
|
||||
blockedLinks: {
|
||||
links: [],
|
||||
isBlocked: () => false,
|
||||
},
|
||||
};
|
||||
globals.set("NewTabUtils", fakeNewTabUtils);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
clock.restore();
|
||||
sandbox.restore();
|
||||
globals.restore();
|
||||
});
|
||||
|
||||
describe("#fetchFromEndpoint", () => {
|
||||
beforeEach(() => {
|
||||
fetchStub.resolves({
|
||||
json: () => Promise.resolve("hi"),
|
||||
ok: true,
|
||||
});
|
||||
});
|
||||
it("should get a response", async () => {
|
||||
const response = await feed.fetchFromEndpoint(DUMMY_ENDPOINT);
|
||||
|
||||
assert.equal(response, "hi");
|
||||
});
|
||||
it("should not send cookies", async () => {
|
||||
await feed.fetchFromEndpoint(DUMMY_ENDPOINT);
|
||||
|
||||
assert.propertyVal(fetchStub.firstCall.args[1], "credentials", "omit");
|
||||
});
|
||||
it("should allow unexpected response", async () => {
|
||||
fetchStub.resolves({ok: false});
|
||||
|
||||
const response = await feed.fetchFromEndpoint(DUMMY_ENDPOINT);
|
||||
|
||||
assert.equal(response, null);
|
||||
});
|
||||
it("should disallow unexpected endpoints", async () => {
|
||||
feed.store.getState = () => ({
|
||||
Prefs: {values: {[ENDPOINTS_PREF_NAME]: "https://other.site"}},
|
||||
});
|
||||
|
||||
const response = await feed.fetchFromEndpoint(DUMMY_ENDPOINT);
|
||||
|
||||
assert.equal(response, null);
|
||||
});
|
||||
it("should allow multiple endpoints", async () => {
|
||||
feed.store.getState = () => ({
|
||||
Prefs: {values: {[ENDPOINTS_PREF_NAME]: `https://other.site,${DUMMY_ENDPOINT}`}},
|
||||
});
|
||||
|
||||
const response = await feed.fetchFromEndpoint(DUMMY_ENDPOINT);
|
||||
|
||||
assert.equal(response, "hi");
|
||||
});
|
||||
});
|
||||
|
||||
describe("#loadLayout", () => {
|
||||
|
@ -534,7 +595,80 @@ describe("DiscoveryStreamFeed", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("#filterSpocs", () => {
|
||||
describe("#filterBlocked", () => {
|
||||
it("should return initial data if spocs are empty", () => {
|
||||
const result = feed.filterBlocked({spocs: []});
|
||||
|
||||
assert.equal(result.spocs.length, 0);
|
||||
});
|
||||
it("should return initial spocs data if links are not blocked", () => {
|
||||
const result = feed.filterBlocked({
|
||||
spocs: [
|
||||
{url: "https://foo.com"},
|
||||
{url: "test.com"},
|
||||
],
|
||||
}, "spocs");
|
||||
assert.equal(result.spocs.length, 2);
|
||||
});
|
||||
it("should return filtered out spocs based on blockedlist", () => {
|
||||
fakeNewTabUtils.blockedLinks.links = [{url: "https://foo.com"}];
|
||||
fakeNewTabUtils.blockedLinks.isBlocked = site => (fakeNewTabUtils.blockedLinks.links[0].url === site.url);
|
||||
|
||||
const result = feed.filterBlocked({
|
||||
spocs: [
|
||||
{url: "https://foo.com"},
|
||||
{url: "test.com"},
|
||||
],
|
||||
}, "spocs");
|
||||
|
||||
assert.lengthOf(result.spocs, 1);
|
||||
assert.equal(result.spocs[0].url, "test.com");
|
||||
assert.notInclude(result.spocs, fakeNewTabUtils.blockedLinks.links[0]);
|
||||
});
|
||||
it("should return initial recommendations data if links are not blocked", () => {
|
||||
const result = feed.filterBlocked({
|
||||
recommendations: [
|
||||
{url: "https://foo.com"},
|
||||
{url: "test.com"},
|
||||
],
|
||||
}, "recommendations");
|
||||
assert.equal(result.recommendations.length, 2);
|
||||
});
|
||||
it("should return filtered out recommendations based on blockedlist", () => {
|
||||
fakeNewTabUtils.blockedLinks.links = [{url: "https://foo.com"}];
|
||||
fakeNewTabUtils.blockedLinks.isBlocked = site => (fakeNewTabUtils.blockedLinks.links[0].url === site.url);
|
||||
|
||||
const result = feed.filterBlocked({
|
||||
recommendations: [
|
||||
{url: "https://foo.com"},
|
||||
{url: "test.com"},
|
||||
],
|
||||
}, "recommendations");
|
||||
|
||||
assert.lengthOf(result.recommendations, 1);
|
||||
assert.equal(result.recommendations[0].url, "test.com");
|
||||
assert.notInclude(result.recommendations, fakeNewTabUtils.blockedLinks.links[0]);
|
||||
});
|
||||
it("filterRecommendations based on blockedlist by passing feed data", () => {
|
||||
fakeNewTabUtils.blockedLinks.links = [{url: "https://foo.com"}];
|
||||
fakeNewTabUtils.blockedLinks.isBlocked = site => (fakeNewTabUtils.blockedLinks.links[0].url === site.url);
|
||||
|
||||
const result = feed.filterRecommendations({
|
||||
data: {
|
||||
recommendations: [
|
||||
{url: "https://foo.com"},
|
||||
{url: "test.com"},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
assert.lengthOf(result.data.recommendations, 1);
|
||||
assert.equal(result.data.recommendations[0].url, "test.com");
|
||||
assert.notInclude(result.data.recommendations, fakeNewTabUtils.blockedLinks.links[0]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#frequencyCapSpocs", () => {
|
||||
it("should return filtered out spocs based on frequency caps", () => {
|
||||
const fakeSpocs = {
|
||||
spocs: [
|
||||
|
@ -565,7 +699,7 @@ describe("DiscoveryStreamFeed", () => {
|
|||
};
|
||||
sandbox.stub(feed, "readImpressionsPref").returns(fakeImpressions);
|
||||
|
||||
const result = feed.filterSpocs(fakeSpocs);
|
||||
const result = feed.frequencyCapSpocs(fakeSpocs);
|
||||
|
||||
assert.equal(result.spocs.length, 1);
|
||||
assert.equal(result.spocs[0].campaign_id, "not-seen");
|
||||
|
|
Загрузка…
Ссылка в новой задаче