зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1682379 - Remove SPOCS Fill event in Activity Stream r=thecount
Differential Revision: https://phabricator.services.mozilla.com/D99805
This commit is contained in:
Родитель
2493b6432d
Коммит
cd43564e6e
|
@ -67,7 +67,6 @@ for (const type of [
|
|||
"DISCOVERY_STREAM_RETRY_FEED",
|
||||
"DISCOVERY_STREAM_SPOCS_CAPS",
|
||||
"DISCOVERY_STREAM_SPOCS_ENDPOINT",
|
||||
"DISCOVERY_STREAM_SPOCS_FILL",
|
||||
"DISCOVERY_STREAM_SPOCS_PLACEMENTS",
|
||||
"DISCOVERY_STREAM_SPOCS_UPDATE",
|
||||
"DISCOVERY_STREAM_SPOC_BLOCKED",
|
||||
|
@ -303,21 +302,6 @@ function ASRouterUserEvent(data) {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* DiscoveryStreamSpocsFill - A telemetry ping indicating a SPOCS Fill event.
|
||||
*
|
||||
* @param {object} data Fields to include in the ping (spoc_fills, etc.)
|
||||
* @param {int} importContext (For testing) Override the import context for testing.
|
||||
* @return {object} An AlsoToMain action
|
||||
*/
|
||||
function DiscoveryStreamSpocsFill(data, importContext = globalImportContext) {
|
||||
const action = {
|
||||
type: actionTypes.DISCOVERY_STREAM_SPOCS_FILL,
|
||||
data,
|
||||
};
|
||||
return importContext === UI_CODE ? AlsoToMain(action) : action;
|
||||
}
|
||||
|
||||
/**
|
||||
* UndesiredEvent - A telemetry ping indicating an undesired state.
|
||||
*
|
||||
|
@ -416,7 +400,6 @@ this.actionCreators = {
|
|||
WebExtEvent,
|
||||
DiscoveryStreamImpressionStats,
|
||||
DiscoveryStreamLoadedContent,
|
||||
DiscoveryStreamSpocsFill,
|
||||
};
|
||||
|
||||
// These are helpers to test for certain kinds of actions
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import { actionCreators as ac } from "common/Actions.jsm";
|
||||
import { CardGrid } from "content-src/components/DiscoveryStreamComponents/CardGrid/CardGrid";
|
||||
import { CollectionCardGrid } from "content-src/components/DiscoveryStreamComponents/CollectionCardGrid/CollectionCardGrid";
|
||||
import { CollapsibleSection } from "content-src/components/CollapsibleSection/CollapsibleSection";
|
||||
|
@ -260,27 +259,13 @@ export class _DiscoveryStreamBase extends React.PureComponent {
|
|||
|
||||
render() {
|
||||
// Select layout render data by adding spocs and position to recommendations
|
||||
const { layoutRender, spocsFill } = selectLayoutRender({
|
||||
const { layoutRender } = selectLayoutRender({
|
||||
state: this.props.DiscoveryStream,
|
||||
prefs: this.props.Prefs.values,
|
||||
rollCache,
|
||||
locale: this.props.locale,
|
||||
});
|
||||
const { config, spocs, feeds } = this.props.DiscoveryStream;
|
||||
|
||||
// Send SPOCS Fill if any. Note that it should not send it again if the same
|
||||
// page gets re-rendered by state changes.
|
||||
if (
|
||||
spocs.loaded &&
|
||||
feeds.loaded &&
|
||||
spocsFill.length &&
|
||||
!this._spocsFillSent
|
||||
) {
|
||||
this.props.dispatch(
|
||||
ac.DiscoveryStreamSpocsFill({ spoc_fills: spocsFill })
|
||||
);
|
||||
this._spocsFillSent = true;
|
||||
}
|
||||
const { config } = this.props.DiscoveryStream;
|
||||
|
||||
// Allow rendering without extracting special components
|
||||
if (!config.collapsible) {
|
||||
|
|
|
@ -11,9 +11,6 @@ export const selectLayoutRender = ({
|
|||
const { layout, feeds, spocs } = state;
|
||||
let spocIndexMap = {};
|
||||
let bufferRollCache = [];
|
||||
// Records the chosen and unchosen spocs by the probability selection.
|
||||
let chosenSpocs = new Set();
|
||||
let unchosenSpocs = new Set();
|
||||
|
||||
function rollForSpocs(data, spocsConfig, spocsData, placementName) {
|
||||
if (!spocIndexMap[placementName] && spocIndexMap[placementName] !== 0) {
|
||||
|
@ -40,10 +37,7 @@ export const selectLayoutRender = ({
|
|||
spocIndexMap[placementName]++;
|
||||
if (!spocs.blocked.includes(spoc.url)) {
|
||||
results.splice(position.index, 0, spoc);
|
||||
chosenSpocs.add(spoc);
|
||||
}
|
||||
} else {
|
||||
unchosenSpocs.add(spoc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -263,47 +257,5 @@ export const selectLayoutRender = ({
|
|||
rollCache.push(...bufferRollCache);
|
||||
}
|
||||
|
||||
// Generate the payload for the SPOCS Fill ping. Note that a SPOC could be rejected
|
||||
// by the `probability_selection` first, then gets chosen for the next position. For
|
||||
// all other SPOCS that never went through the probabilistic selection, its reason will
|
||||
// be "out_of_position".
|
||||
let spocsFill = [];
|
||||
if (
|
||||
spocs.loaded &&
|
||||
feeds.loaded &&
|
||||
spocs.data.spocs &&
|
||||
spocs.data.spocs.items
|
||||
) {
|
||||
const chosenSpocsFill = [...chosenSpocs].map(spoc => ({
|
||||
id: spoc.id,
|
||||
reason: "n/a",
|
||||
displayed: 1,
|
||||
full_recalc: 0,
|
||||
}));
|
||||
const unchosenSpocsFill = [...unchosenSpocs]
|
||||
.filter(spoc => !chosenSpocs.has(spoc))
|
||||
.map(spoc => ({
|
||||
id: spoc.id,
|
||||
reason: "probability_selection",
|
||||
displayed: 0,
|
||||
full_recalc: 0,
|
||||
}));
|
||||
const outOfPositionSpocsFill = spocs.data.spocs.items
|
||||
.slice(spocIndexMap.spocs)
|
||||
.filter(spoc => !unchosenSpocs.has(spoc))
|
||||
.map(spoc => ({
|
||||
id: spoc.id,
|
||||
reason: "out_of_position",
|
||||
displayed: 0,
|
||||
full_recalc: 0,
|
||||
}));
|
||||
|
||||
spocsFill = [
|
||||
...chosenSpocsFill,
|
||||
...unchosenSpocsFill,
|
||||
...outOfPositionSpocsFill,
|
||||
];
|
||||
}
|
||||
|
||||
return { spocsFill, layoutRender };
|
||||
return { layoutRender };
|
||||
};
|
||||
|
|
|
@ -205,7 +205,7 @@ const globalImportContext = typeof Window === "undefined" ? BACKGROUND_PROCESS :
|
|||
// }
|
||||
const actionTypes = {};
|
||||
|
||||
for (const type of ["ABOUT_SPONSORED_TOP_SITES", "ADDONS_INFO_REQUEST", "ADDONS_INFO_RESPONSE", "ARCHIVE_FROM_POCKET", "AS_ROUTER_INITIALIZED", "AS_ROUTER_PREF_CHANGED", "AS_ROUTER_TARGETING_UPDATE", "AS_ROUTER_TELEMETRY_USER_EVENT", "BLOCK_URL", "BOOKMARK_URL", "CLEAR_PREF", "COPY_DOWNLOAD_LINK", "DELETE_BOOKMARK_BY_ID", "DELETE_FROM_POCKET", "DELETE_HISTORY_URL", "DIALOG_CANCEL", "DIALOG_OPEN", "DISCOVERY_STREAM_COLLECTION_DISMISSIBLE_TOGGLE", "DISCOVERY_STREAM_CONFIG_CHANGE", "DISCOVERY_STREAM_CONFIG_RESET", "DISCOVERY_STREAM_CONFIG_RESET_DEFAULTS", "DISCOVERY_STREAM_CONFIG_SETUP", "DISCOVERY_STREAM_CONFIG_SET_VALUE", "DISCOVERY_STREAM_DEV_EXPIRE_CACHE", "DISCOVERY_STREAM_DEV_IDLE_DAILY", "DISCOVERY_STREAM_DEV_SYNC_RS", "DISCOVERY_STREAM_DEV_SYSTEM_TICK", "DISCOVERY_STREAM_FEEDS_UPDATE", "DISCOVERY_STREAM_FEED_UPDATE", "DISCOVERY_STREAM_IMPRESSION_STATS", "DISCOVERY_STREAM_LAYOUT_RESET", "DISCOVERY_STREAM_LAYOUT_UPDATE", "DISCOVERY_STREAM_LINK_BLOCKED", "DISCOVERY_STREAM_LOADED_CONTENT", "DISCOVERY_STREAM_PERSONALIZATION_INIT", "DISCOVERY_STREAM_PERSONALIZATION_LAST_UPDATED", "DISCOVERY_STREAM_PERSONALIZATION_VERSION", "DISCOVERY_STREAM_PERSONALIZATION_VERSION_TOGGLE", "DISCOVERY_STREAM_RETRY_FEED", "DISCOVERY_STREAM_SPOCS_CAPS", "DISCOVERY_STREAM_SPOCS_ENDPOINT", "DISCOVERY_STREAM_SPOCS_FILL", "DISCOVERY_STREAM_SPOCS_PLACEMENTS", "DISCOVERY_STREAM_SPOCS_UPDATE", "DISCOVERY_STREAM_SPOC_BLOCKED", "DISCOVERY_STREAM_SPOC_IMPRESSION", "DOWNLOAD_CHANGED", "FAKE_FOCUS_SEARCH", "FILL_SEARCH_TERM", "HANDOFF_SEARCH_TO_AWESOMEBAR", "HIDE_PRIVACY_INFO", "HIDE_SEARCH", "INIT", "NEW_TAB_INIT", "NEW_TAB_INITIAL_STATE", "NEW_TAB_LOAD", "NEW_TAB_REHYDRATED", "NEW_TAB_STATE_REQUEST", "NEW_TAB_UNLOAD", "OPEN_DOWNLOAD_FILE", "OPEN_LINK", "OPEN_NEW_WINDOW", "OPEN_PRIVATE_WINDOW", "OPEN_WEBEXT_SETTINGS", "PARTNER_LINK_ATTRIBUTION", "PLACES_BOOKMARK_ADDED", "PLACES_BOOKMARK_REMOVED", "PLACES_HISTORY_CLEARED", "PLACES_LINKS_CHANGED", "PLACES_LINK_BLOCKED", "PLACES_LINK_DELETED", "PLACES_SAVED_TO_POCKET", "POCKET_CTA", "POCKET_LINK_DELETED_OR_ARCHIVED", "POCKET_LOGGED_IN", "POCKET_WAITING_FOR_SPOC", "PREFS_INITIAL_VALUES", "PREF_CHANGED", "PREVIEW_REQUEST", "PREVIEW_REQUEST_CANCEL", "PREVIEW_RESPONSE", "REMOVE_DOWNLOAD_FILE", "RICH_ICON_MISSING", "SAVE_SESSION_PERF_DATA", "SAVE_TO_POCKET", "SCREENSHOT_UPDATED", "SECTION_DEREGISTER", "SECTION_DISABLE", "SECTION_ENABLE", "SECTION_MOVE", "SECTION_OPTIONS_CHANGED", "SECTION_REGISTER", "SECTION_UPDATE", "SECTION_UPDATE_CARD", "SETTINGS_CLOSE", "SETTINGS_OPEN", "SET_PREF", "SHOW_DOWNLOAD_FILE", "SHOW_FIREFOX_ACCOUNTS", "SHOW_PRIVACY_INFO", "SHOW_SEARCH", "SKIPPED_SIGNIN", "SNIPPETS_BLOCKLIST_CLEARED", "SNIPPETS_BLOCKLIST_UPDATED", "SNIPPETS_DATA", "SNIPPETS_PREVIEW_MODE", "SNIPPETS_RESET", "SNIPPET_BLOCKED", "SUBMIT_EMAIL", "SUBMIT_SIGNIN", "SYSTEM_TICK", "TELEMETRY_IMPRESSION_STATS", "TELEMETRY_UNDESIRED_EVENT", "TELEMETRY_USER_EVENT", "TOP_SITES_CANCEL_EDIT", "TOP_SITES_CLOSE_SEARCH_SHORTCUTS_MODAL", "TOP_SITES_EDIT", "TOP_SITES_INSERT", "TOP_SITES_OPEN_SEARCH_SHORTCUTS_MODAL", "TOP_SITES_PIN", "TOP_SITES_PREFS_UPDATED", "TOP_SITES_UNPIN", "TOP_SITES_UPDATED", "TOTAL_BOOKMARKS_REQUEST", "TOTAL_BOOKMARKS_RESPONSE", "UNINIT", "UPDATE_PINNED_SEARCH_SHORTCUTS", "UPDATE_SEARCH_SHORTCUTS", "UPDATE_SECTION_PREFS", "WEBEXT_CLICK", "WEBEXT_DISMISS"]) {
|
||||
for (const type of ["ABOUT_SPONSORED_TOP_SITES", "ADDONS_INFO_REQUEST", "ADDONS_INFO_RESPONSE", "ARCHIVE_FROM_POCKET", "AS_ROUTER_INITIALIZED", "AS_ROUTER_PREF_CHANGED", "AS_ROUTER_TARGETING_UPDATE", "AS_ROUTER_TELEMETRY_USER_EVENT", "BLOCK_URL", "BOOKMARK_URL", "CLEAR_PREF", "COPY_DOWNLOAD_LINK", "DELETE_BOOKMARK_BY_ID", "DELETE_FROM_POCKET", "DELETE_HISTORY_URL", "DIALOG_CANCEL", "DIALOG_OPEN", "DISCOVERY_STREAM_COLLECTION_DISMISSIBLE_TOGGLE", "DISCOVERY_STREAM_CONFIG_CHANGE", "DISCOVERY_STREAM_CONFIG_RESET", "DISCOVERY_STREAM_CONFIG_RESET_DEFAULTS", "DISCOVERY_STREAM_CONFIG_SETUP", "DISCOVERY_STREAM_CONFIG_SET_VALUE", "DISCOVERY_STREAM_DEV_EXPIRE_CACHE", "DISCOVERY_STREAM_DEV_IDLE_DAILY", "DISCOVERY_STREAM_DEV_SYNC_RS", "DISCOVERY_STREAM_DEV_SYSTEM_TICK", "DISCOVERY_STREAM_FEEDS_UPDATE", "DISCOVERY_STREAM_FEED_UPDATE", "DISCOVERY_STREAM_IMPRESSION_STATS", "DISCOVERY_STREAM_LAYOUT_RESET", "DISCOVERY_STREAM_LAYOUT_UPDATE", "DISCOVERY_STREAM_LINK_BLOCKED", "DISCOVERY_STREAM_LOADED_CONTENT", "DISCOVERY_STREAM_PERSONALIZATION_INIT", "DISCOVERY_STREAM_PERSONALIZATION_LAST_UPDATED", "DISCOVERY_STREAM_PERSONALIZATION_VERSION", "DISCOVERY_STREAM_PERSONALIZATION_VERSION_TOGGLE", "DISCOVERY_STREAM_RETRY_FEED", "DISCOVERY_STREAM_SPOCS_CAPS", "DISCOVERY_STREAM_SPOCS_ENDPOINT", "DISCOVERY_STREAM_SPOCS_PLACEMENTS", "DISCOVERY_STREAM_SPOCS_UPDATE", "DISCOVERY_STREAM_SPOC_BLOCKED", "DISCOVERY_STREAM_SPOC_IMPRESSION", "DOWNLOAD_CHANGED", "FAKE_FOCUS_SEARCH", "FILL_SEARCH_TERM", "HANDOFF_SEARCH_TO_AWESOMEBAR", "HIDE_PRIVACY_INFO", "HIDE_SEARCH", "INIT", "NEW_TAB_INIT", "NEW_TAB_INITIAL_STATE", "NEW_TAB_LOAD", "NEW_TAB_REHYDRATED", "NEW_TAB_STATE_REQUEST", "NEW_TAB_UNLOAD", "OPEN_DOWNLOAD_FILE", "OPEN_LINK", "OPEN_NEW_WINDOW", "OPEN_PRIVATE_WINDOW", "OPEN_WEBEXT_SETTINGS", "PARTNER_LINK_ATTRIBUTION", "PLACES_BOOKMARK_ADDED", "PLACES_BOOKMARK_REMOVED", "PLACES_HISTORY_CLEARED", "PLACES_LINKS_CHANGED", "PLACES_LINK_BLOCKED", "PLACES_LINK_DELETED", "PLACES_SAVED_TO_POCKET", "POCKET_CTA", "POCKET_LINK_DELETED_OR_ARCHIVED", "POCKET_LOGGED_IN", "POCKET_WAITING_FOR_SPOC", "PREFS_INITIAL_VALUES", "PREF_CHANGED", "PREVIEW_REQUEST", "PREVIEW_REQUEST_CANCEL", "PREVIEW_RESPONSE", "REMOVE_DOWNLOAD_FILE", "RICH_ICON_MISSING", "SAVE_SESSION_PERF_DATA", "SAVE_TO_POCKET", "SCREENSHOT_UPDATED", "SECTION_DEREGISTER", "SECTION_DISABLE", "SECTION_ENABLE", "SECTION_MOVE", "SECTION_OPTIONS_CHANGED", "SECTION_REGISTER", "SECTION_UPDATE", "SECTION_UPDATE_CARD", "SETTINGS_CLOSE", "SETTINGS_OPEN", "SET_PREF", "SHOW_DOWNLOAD_FILE", "SHOW_FIREFOX_ACCOUNTS", "SHOW_PRIVACY_INFO", "SHOW_SEARCH", "SKIPPED_SIGNIN", "SNIPPETS_BLOCKLIST_CLEARED", "SNIPPETS_BLOCKLIST_UPDATED", "SNIPPETS_DATA", "SNIPPETS_PREVIEW_MODE", "SNIPPETS_RESET", "SNIPPET_BLOCKED", "SUBMIT_EMAIL", "SUBMIT_SIGNIN", "SYSTEM_TICK", "TELEMETRY_IMPRESSION_STATS", "TELEMETRY_UNDESIRED_EVENT", "TELEMETRY_USER_EVENT", "TOP_SITES_CANCEL_EDIT", "TOP_SITES_CLOSE_SEARCH_SHORTCUTS_MODAL", "TOP_SITES_EDIT", "TOP_SITES_INSERT", "TOP_SITES_OPEN_SEARCH_SHORTCUTS_MODAL", "TOP_SITES_PIN", "TOP_SITES_PREFS_UPDATED", "TOP_SITES_UNPIN", "TOP_SITES_UPDATED", "TOTAL_BOOKMARKS_REQUEST", "TOTAL_BOOKMARKS_RESPONSE", "UNINIT", "UPDATE_PINNED_SEARCH_SHORTCUTS", "UPDATE_SEARCH_SHORTCUTS", "UPDATE_SECTION_PREFS", "WEBEXT_CLICK", "WEBEXT_DISMISS"]) {
|
||||
actionTypes[type] = type;
|
||||
} // Helper function for creating routed actions between content and main
|
||||
// Not intended to be used by consumers
|
||||
|
@ -358,22 +358,6 @@ function ASRouterUserEvent(data) {
|
|||
data
|
||||
});
|
||||
}
|
||||
/**
|
||||
* DiscoveryStreamSpocsFill - A telemetry ping indicating a SPOCS Fill event.
|
||||
*
|
||||
* @param {object} data Fields to include in the ping (spoc_fills, etc.)
|
||||
* @param {int} importContext (For testing) Override the import context for testing.
|
||||
* @return {object} An AlsoToMain action
|
||||
*/
|
||||
|
||||
|
||||
function DiscoveryStreamSpocsFill(data, importContext = globalImportContext) {
|
||||
const action = {
|
||||
type: actionTypes.DISCOVERY_STREAM_SPOCS_FILL,
|
||||
data
|
||||
};
|
||||
return importContext === UI_CODE ? AlsoToMain(action) : action;
|
||||
}
|
||||
/**
|
||||
* UndesiredEvent - A telemetry ping indicating an undesired state.
|
||||
*
|
||||
|
@ -476,8 +460,7 @@ var actionCreators = {
|
|||
SetPref,
|
||||
WebExtEvent,
|
||||
DiscoveryStreamImpressionStats,
|
||||
DiscoveryStreamLoadedContent,
|
||||
DiscoveryStreamSpocsFill
|
||||
DiscoveryStreamLoadedContent
|
||||
}; // These are helpers to test for certain kinds of actions
|
||||
|
||||
var actionUtils = {
|
||||
|
@ -3113,26 +3096,25 @@ __webpack_require__.r(__webpack_exports__);
|
|||
/* WEBPACK VAR INJECTION */(function(global) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isAllowedCSS", function() { return isAllowedCSS; });
|
||||
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "_DiscoveryStreamBase", function() { return _DiscoveryStreamBase; });
|
||||
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DiscoveryStreamBase", function() { return DiscoveryStreamBase; });
|
||||
/* harmony import */ var common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_CardGrid_CardGrid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(17);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_CollectionCardGrid_CollectionCardGrid__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(32);
|
||||
/* harmony import */ var content_src_components_CollapsibleSection_CollapsibleSection__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(34);
|
||||
/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(7);
|
||||
/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(react_redux__WEBPACK_IMPORTED_MODULE_4__);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_DSMessage_DSMessage__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(39);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_DSPrivacyModal_DSPrivacyModal__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(40);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_DSSignup_DSSignup__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(42);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_DSTextPromo_DSTextPromo__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(43);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_Hero_Hero__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(44);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_Highlights_Highlights__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(46);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_HorizontalRule_HorizontalRule__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(59);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_List_List__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(45);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_Navigation_Navigation__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(60);
|
||||
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(8);
|
||||
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_14___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_14__);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_SectionTitle_SectionTitle__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(61);
|
||||
/* harmony import */ var content_src_lib_selectLayoutRender__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(62);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_TopSites_TopSites__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(63);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_CardGrid_CardGrid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(17);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_CollectionCardGrid_CollectionCardGrid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(32);
|
||||
/* harmony import */ var content_src_components_CollapsibleSection_CollapsibleSection__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(34);
|
||||
/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(7);
|
||||
/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react_redux__WEBPACK_IMPORTED_MODULE_3__);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_DSMessage_DSMessage__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(39);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_DSPrivacyModal_DSPrivacyModal__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(40);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_DSSignup_DSSignup__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(42);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_DSTextPromo_DSTextPromo__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(43);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_Hero_Hero__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(44);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_Highlights_Highlights__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(46);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_HorizontalRule_HorizontalRule__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(59);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_List_List__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(45);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_Navigation_Navigation__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(60);
|
||||
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(8);
|
||||
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_13___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_13__);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_SectionTitle_SectionTitle__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(61);
|
||||
/* harmony import */ var content_src_lib_selectLayoutRender__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(62);
|
||||
/* harmony import */ var content_src_components_DiscoveryStreamComponents_TopSites_TopSites__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(63);
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
@ -3153,7 +3135,6 @@ __webpack_require__.r(__webpack_exports__);
|
|||
|
||||
|
||||
|
||||
|
||||
const ALLOWED_CSS_URL_PREFIXES = ["chrome://", "resource://", "https://img-getpocket.cdn.mozilla.net/"];
|
||||
const DUMMY_CSS_SELECTOR = "DUMMY#CSS.SELECTOR";
|
||||
let rollCache = []; // Cache of random probability values for a spoc position
|
||||
|
@ -3174,7 +3155,7 @@ function isAllowedCSS(property, value) {
|
|||
const urls = value.match(/url\("[^"]+"\)/g);
|
||||
return !urls || urls.every(url => ALLOWED_CSS_URL_PREFIXES.some(prefix => url.slice(5).startsWith(prefix)));
|
||||
}
|
||||
class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a.PureComponent {
|
||||
class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_13___default.a.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onStyleMount = this.onStyleMount.bind(this);
|
||||
|
@ -3233,7 +3214,7 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
|
|||
|
||||
switch (component.type) {
|
||||
case "Highlights":
|
||||
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_Highlights_Highlights__WEBPACK_IMPORTED_MODULE_10__["Highlights"], null);
|
||||
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_Highlights_Highlights__WEBPACK_IMPORTED_MODULE_9__["Highlights"], null);
|
||||
|
||||
case "TopSites":
|
||||
let promoAlignment;
|
||||
|
@ -3242,28 +3223,28 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
|
|||
promoAlignment = component.spocs.positions[0].index === 0 ? "left" : "right";
|
||||
}
|
||||
|
||||
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_TopSites_TopSites__WEBPACK_IMPORTED_MODULE_17__["TopSites"], {
|
||||
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_TopSites_TopSites__WEBPACK_IMPORTED_MODULE_16__["TopSites"], {
|
||||
header: component.header,
|
||||
data: component.data,
|
||||
promoAlignment: promoAlignment
|
||||
});
|
||||
|
||||
case "TextPromo":
|
||||
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_DSTextPromo_DSTextPromo__WEBPACK_IMPORTED_MODULE_8__["DSTextPromo"], {
|
||||
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_DSTextPromo_DSTextPromo__WEBPACK_IMPORTED_MODULE_7__["DSTextPromo"], {
|
||||
dispatch: this.props.dispatch,
|
||||
type: component.type,
|
||||
data: component.data
|
||||
});
|
||||
|
||||
case "Signup":
|
||||
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_DSSignup_DSSignup__WEBPACK_IMPORTED_MODULE_7__["DSSignup"], {
|
||||
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_DSSignup_DSSignup__WEBPACK_IMPORTED_MODULE_6__["DSSignup"], {
|
||||
dispatch: this.props.dispatch,
|
||||
type: component.type,
|
||||
data: component.data
|
||||
});
|
||||
|
||||
case "Message":
|
||||
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_DSMessage_DSMessage__WEBPACK_IMPORTED_MODULE_5__["DSMessage"], {
|
||||
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_DSMessage_DSMessage__WEBPACK_IMPORTED_MODULE_4__["DSMessage"], {
|
||||
title: component.header && component.header.title,
|
||||
subtitle: component.header && component.header.subtitle,
|
||||
link_text: component.header && component.header.link_text,
|
||||
|
@ -3272,12 +3253,12 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
|
|||
});
|
||||
|
||||
case "SectionTitle":
|
||||
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_SectionTitle_SectionTitle__WEBPACK_IMPORTED_MODULE_15__["SectionTitle"], {
|
||||
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_SectionTitle_SectionTitle__WEBPACK_IMPORTED_MODULE_14__["SectionTitle"], {
|
||||
header: component.header
|
||||
});
|
||||
|
||||
case "Navigation":
|
||||
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_Navigation_Navigation__WEBPACK_IMPORTED_MODULE_13__["Navigation"], {
|
||||
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_Navigation_Navigation__WEBPACK_IMPORTED_MODULE_12__["Navigation"], {
|
||||
dispatch: this.props.dispatch,
|
||||
links: component.properties.links,
|
||||
alignment: component.properties.alignment,
|
||||
|
@ -3290,7 +3271,7 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
|
|||
const {
|
||||
DiscoveryStream
|
||||
} = this.props;
|
||||
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_CollectionCardGrid_CollectionCardGrid__WEBPACK_IMPORTED_MODULE_2__["CollectionCardGrid"], {
|
||||
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_CollectionCardGrid_CollectionCardGrid__WEBPACK_IMPORTED_MODULE_1__["CollectionCardGrid"], {
|
||||
data: component.data,
|
||||
feed: component.feed,
|
||||
spocs: DiscoveryStream.spocs,
|
||||
|
@ -3305,7 +3286,7 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
|
|||
});
|
||||
|
||||
case "CardGrid":
|
||||
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_CardGrid_CardGrid__WEBPACK_IMPORTED_MODULE_1__["CardGrid"], {
|
||||
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_CardGrid_CardGrid__WEBPACK_IMPORTED_MODULE_0__["CardGrid"], {
|
||||
enable_video_playheads: !!component.properties.enable_video_playheads,
|
||||
title: component.header && component.header.title,
|
||||
display_variant: component.properties.display_variant,
|
||||
|
@ -3320,7 +3301,7 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
|
|||
});
|
||||
|
||||
case "Hero":
|
||||
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_Hero_Hero__WEBPACK_IMPORTED_MODULE_9__["Hero"], {
|
||||
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_Hero_Hero__WEBPACK_IMPORTED_MODULE_8__["Hero"], {
|
||||
subComponentType: embedWidth >= 9 ? `cards` : `list`,
|
||||
feed: component.feed,
|
||||
title: component.header && component.header.title,
|
||||
|
@ -3332,10 +3313,10 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
|
|||
});
|
||||
|
||||
case "HorizontalRule":
|
||||
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_HorizontalRule_HorizontalRule__WEBPACK_IMPORTED_MODULE_11__["HorizontalRule"], null);
|
||||
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_HorizontalRule_HorizontalRule__WEBPACK_IMPORTED_MODULE_10__["HorizontalRule"], null);
|
||||
|
||||
case "List":
|
||||
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_List_List__WEBPACK_IMPORTED_MODULE_12__["List"], {
|
||||
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_List_List__WEBPACK_IMPORTED_MODULE_11__["List"], {
|
||||
data: component.data,
|
||||
feed: component.feed,
|
||||
fullWidth: component.properties.full_width,
|
||||
|
@ -3348,7 +3329,7 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
|
|||
});
|
||||
|
||||
default:
|
||||
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div", null, component.type);
|
||||
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement("div", null, component.type);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3356,7 +3337,7 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
|
|||
// Use json string as both the key and styles to render so React knows when
|
||||
// to unmount and mount a new instance for new styles.
|
||||
const json = JSON.stringify(styles);
|
||||
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("style", {
|
||||
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement("style", {
|
||||
key: json,
|
||||
"data-styles": json,
|
||||
ref: this.onStyleMount
|
||||
|
@ -3372,28 +3353,16 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
|
|||
render() {
|
||||
// Select layout render data by adding spocs and position to recommendations
|
||||
const {
|
||||
layoutRender,
|
||||
spocsFill
|
||||
} = Object(content_src_lib_selectLayoutRender__WEBPACK_IMPORTED_MODULE_16__["selectLayoutRender"])({
|
||||
layoutRender
|
||||
} = Object(content_src_lib_selectLayoutRender__WEBPACK_IMPORTED_MODULE_15__["selectLayoutRender"])({
|
||||
state: this.props.DiscoveryStream,
|
||||
prefs: this.props.Prefs.values,
|
||||
rollCache,
|
||||
locale: this.props.locale
|
||||
});
|
||||
const {
|
||||
config,
|
||||
spocs,
|
||||
feeds
|
||||
} = this.props.DiscoveryStream; // Send SPOCS Fill if any. Note that it should not send it again if the same
|
||||
// page gets re-rendered by state changes.
|
||||
|
||||
if (spocs.loaded && feeds.loaded && spocsFill.length && !this._spocsFillSent) {
|
||||
this.props.dispatch(common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__["actionCreators"].DiscoveryStreamSpocsFill({
|
||||
spoc_fills: spocsFill
|
||||
}));
|
||||
this._spocsFillSent = true;
|
||||
} // Allow rendering without extracting special components
|
||||
|
||||
config
|
||||
} = this.props.DiscoveryStream; // Allow rendering without extracting special components
|
||||
|
||||
if (!config.collapsible) {
|
||||
return this.renderLayout(layoutRender);
|
||||
|
@ -3437,7 +3406,7 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
|
|||
}
|
||||
}; // Render a DS-style TopSites then the rest if any in a collapsible section
|
||||
|
||||
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(react__WEBPACK_IMPORTED_MODULE_14___default.a.Fragment, null, this.props.DiscoveryStream.isPrivacyInfoModalVisible && react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_DSPrivacyModal_DSPrivacyModal__WEBPACK_IMPORTED_MODULE_6__["DSPrivacyModal"], {
|
||||
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(react__WEBPACK_IMPORTED_MODULE_13___default.a.Fragment, null, this.props.DiscoveryStream.isPrivacyInfoModalVisible && react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_DSPrivacyModal_DSPrivacyModal__WEBPACK_IMPORTED_MODULE_5__["DSPrivacyModal"], {
|
||||
dispatch: this.props.dispatch
|
||||
}), topSites && this.renderLayout([{
|
||||
width: 12,
|
||||
|
@ -3445,7 +3414,7 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
|
|||
}]), sponsoredCollection && this.renderLayout([{
|
||||
width: 12,
|
||||
components: [sponsoredCollection]
|
||||
}]), !!layoutRender.length && react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_CollapsibleSection_CollapsibleSection__WEBPACK_IMPORTED_MODULE_3__["CollapsibleSection"], {
|
||||
}]), !!layoutRender.length && react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_CollapsibleSection_CollapsibleSection__WEBPACK_IMPORTED_MODULE_2__["CollapsibleSection"], {
|
||||
className: "ds-layout",
|
||||
collapsed: topStories.pref.collapsed,
|
||||
dispatch: this.props.dispatch,
|
||||
|
@ -3472,12 +3441,12 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
|
|||
|
||||
renderLayout(layoutRender) {
|
||||
const styles = [];
|
||||
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div", {
|
||||
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement("div", {
|
||||
className: "discovery-stream ds-layout"
|
||||
}, layoutRender.map((row, rowIndex) => react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div", {
|
||||
}, layoutRender.map((row, rowIndex) => react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement("div", {
|
||||
key: `row-${rowIndex}`,
|
||||
className: `ds-column ds-column-${row.width}`
|
||||
}, react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div", {
|
||||
}, react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement("div", {
|
||||
className: "ds-column-grid"
|
||||
}, row.components.map((component, componentIndex) => {
|
||||
if (!component) {
|
||||
|
@ -3485,14 +3454,14 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
|
|||
}
|
||||
|
||||
styles[rowIndex] = [...(styles[rowIndex] || []), component.styles];
|
||||
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div", {
|
||||
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement("div", {
|
||||
key: `component-${componentIndex}`
|
||||
}, this.renderComponent(component, row.width));
|
||||
})))), this.renderStyles(styles));
|
||||
}
|
||||
|
||||
}
|
||||
const DiscoveryStreamBase = Object(react_redux__WEBPACK_IMPORTED_MODULE_4__["connect"])(state => ({
|
||||
const DiscoveryStreamBase = Object(react_redux__WEBPACK_IMPORTED_MODULE_3__["connect"])(state => ({
|
||||
DiscoveryStream: state.DiscoveryStream,
|
||||
Prefs: state.Prefs,
|
||||
Sections: state.Sections,
|
||||
|
@ -9751,10 +9720,7 @@ const selectLayoutRender = ({
|
|||
spocs
|
||||
} = state;
|
||||
let spocIndexMap = {};
|
||||
let bufferRollCache = []; // Records the chosen and unchosen spocs by the probability selection.
|
||||
|
||||
let chosenSpocs = new Set();
|
||||
let unchosenSpocs = new Set();
|
||||
let bufferRollCache = [];
|
||||
|
||||
function rollForSpocs(data, spocsConfig, spocsData, placementName) {
|
||||
if (!spocIndexMap[placementName] && spocIndexMap[placementName] !== 0) {
|
||||
|
@ -9786,10 +9752,7 @@ const selectLayoutRender = ({
|
|||
|
||||
if (!spocs.blocked.includes(spoc.url)) {
|
||||
results.splice(position.index, 0, spoc);
|
||||
chosenSpocs.add(spoc);
|
||||
}
|
||||
} else {
|
||||
unchosenSpocs.add(spoc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9964,38 +9927,9 @@ const selectLayoutRender = ({
|
|||
|
||||
if (!rollCache.length) {
|
||||
rollCache.push(...bufferRollCache);
|
||||
} // Generate the payload for the SPOCS Fill ping. Note that a SPOC could be rejected
|
||||
// by the `probability_selection` first, then gets chosen for the next position. For
|
||||
// all other SPOCS that never went through the probabilistic selection, its reason will
|
||||
// be "out_of_position".
|
||||
|
||||
|
||||
let spocsFill = [];
|
||||
|
||||
if (spocs.loaded && feeds.loaded && spocs.data.spocs && spocs.data.spocs.items) {
|
||||
const chosenSpocsFill = [...chosenSpocs].map(spoc => ({
|
||||
id: spoc.id,
|
||||
reason: "n/a",
|
||||
displayed: 1,
|
||||
full_recalc: 0
|
||||
}));
|
||||
const unchosenSpocsFill = [...unchosenSpocs].filter(spoc => !chosenSpocs.has(spoc)).map(spoc => ({
|
||||
id: spoc.id,
|
||||
reason: "probability_selection",
|
||||
displayed: 0,
|
||||
full_recalc: 0
|
||||
}));
|
||||
const outOfPositionSpocsFill = spocs.data.spocs.items.slice(spocIndexMap.spocs).filter(spoc => !unchosenSpocs.has(spoc)).map(spoc => ({
|
||||
id: spoc.id,
|
||||
reason: "out_of_position",
|
||||
displayed: 0,
|
||||
full_recalc: 0
|
||||
}));
|
||||
spocsFill = [...chosenSpocsFill, ...unchosenSpocsFill, ...outOfPositionSpocsFill];
|
||||
}
|
||||
|
||||
return {
|
||||
spocsFill,
|
||||
layoutRender
|
||||
};
|
||||
};
|
||||
|
|
|
@ -136,30 +136,6 @@ Schema definitions/validations that can be used for tests can be found in `syste
|
|||
}
|
||||
```
|
||||
|
||||
## Example Discovery Stream `SPOCS Fill` log
|
||||
|
||||
```js
|
||||
{
|
||||
// both "client_id" and "session_id" are set to "n/a" in this ping.
|
||||
"client_id": "n/a",
|
||||
"session_id": "n/a",
|
||||
"impression_id": "{005deed0-e3e4-4c02-a041-17405fd703f6}",
|
||||
"addon_version": "20180710100040",
|
||||
"locale": "en-US",
|
||||
"version": "68",
|
||||
"release_channel": "release",
|
||||
"spoc_fills": [
|
||||
{"id": 10000, displayed: 0, reason: "frequency_cap", full_recalc: 1},
|
||||
{"id": 10001, displayed: 0, reason: "blocked_by_user", full_recalc: 1},
|
||||
{"id": 10002, displayed: 0, reason: "below_min_score", full_recalc: 1},
|
||||
{"id": 10003, displayed: 0, reason: "flight_duplicate", full_recalc: 1},
|
||||
{"id": 10004, displayed: 0, reason: "probability_selection", full_recalc: 0},
|
||||
{"id": 10004, displayed: 0, reason: "out_of_position", full_recalc: 0},
|
||||
{"id": 10005, displayed: 1, reason: "n/a", full_recalc: 0}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Example Activity Stream `Router` Pings
|
||||
|
||||
```js
|
||||
|
|
|
@ -689,36 +689,6 @@ These pings record user interaction with the save to Pocket button.
|
|||
}
|
||||
```
|
||||
|
||||
## Discovery Stream SPOCS Fill ping
|
||||
|
||||
This reports the internal status of Pocket SPOCS (Sponsored Contents).
|
||||
|
||||
```js
|
||||
{
|
||||
// both "client_id" and "session_id" are set to "n/a" in this ping.
|
||||
"client_id": "n/a",
|
||||
"session_id": "n/a",
|
||||
"impression_id": "{005deed0-e3e4-4c02-a041-17405fd703f6}",
|
||||
"addon_version": "20180710100040",
|
||||
"locale": "en-US",
|
||||
"version": "68",
|
||||
"release_channel": "release",
|
||||
"experiments": {
|
||||
"experiment_1": {"branch": "control"},
|
||||
"experiment_2": {"branch": "treatment"}
|
||||
},
|
||||
"spoc_fills": [
|
||||
{"id": 10000, displayed: 0, reason: "frequency_cap", full_recalc: 1},
|
||||
{"id": 10001, displayed: 0, reason: "blocked_by_user", full_recalc: 1},
|
||||
{"id": 10002, displayed: 0, reason: "below_min_score", full_recalc: 1},
|
||||
{"id": 10003, displayed: 0, reason: "campaign_duplicate", full_recalc: 1},
|
||||
{"id": 10004, displayed: 0, reason: "probability_selection", full_recalc: 0},
|
||||
{"id": 10004, displayed: 0, reason: "out_of_position", full_recalc: 0},
|
||||
{"id": 10005, displayed: 1, reason: "n/a", full_recalc: 0}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Undesired event pings
|
||||
|
||||
These pings record the undesired events happen in the addon for further investigation.
|
||||
|
|
|
@ -97,35 +97,6 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
|
|||
return impressionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send SPOCS Fill telemetry.
|
||||
* @param {object} filteredItems An object keyed on filter reasons, and the value
|
||||
* is a list of SPOCS.
|
||||
* reasons: blocked_by_user, frequency_cap, below_min_score, flight_duplicate
|
||||
* @param {boolean} fullRecalc A boolean indicating if it's a full recalculation.
|
||||
* Calling `loadSpocs` will be treated as a full recalculation.
|
||||
* Whereas responding the action "DISCOVERY_STREAM_SPOC_IMPRESSION"
|
||||
* is not a full recalculation.
|
||||
*/
|
||||
_sendSpocsFill(filteredItems, fullRecalc) {
|
||||
const full_recalc = fullRecalc ? 1 : 0;
|
||||
const spocsFill = [];
|
||||
for (const [reason, items] of Object.entries(filteredItems)) {
|
||||
items.forEach(item => {
|
||||
// Only send SPOCS (i.e. it has a flight_id)
|
||||
if (item.flight_id) {
|
||||
spocsFill.push({ reason, full_recalc, id: item.id, displayed: 0 });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (spocsFill.length) {
|
||||
this.store.dispatch(
|
||||
ac.DiscoveryStreamSpocsFill({ spoc_fills: spocsFill })
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
finalLayoutEndpoint(url, apiKey) {
|
||||
if (url.includes("$apiKey") && !apiKey) {
|
||||
throw new Error(
|
||||
|
@ -692,10 +663,6 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
|
|||
const cachedData = (await this.cache.get()) || {};
|
||||
let spocsState;
|
||||
|
||||
let frequencyCapped = [];
|
||||
let blockedItems = [];
|
||||
let belowMinScore = [];
|
||||
|
||||
const { placements } = this.store.getState().DiscoveryStream.spocs;
|
||||
|
||||
if (this.showSpocs) {
|
||||
|
@ -775,24 +742,14 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
|
|||
normalizedSpocsItems
|
||||
);
|
||||
|
||||
const {
|
||||
data: capResult,
|
||||
filtered: caps,
|
||||
} = this.frequencyCapSpocs(migratedSpocs);
|
||||
frequencyCapped = [...frequencyCapped, ...caps];
|
||||
const { data: capResult } = this.frequencyCapSpocs(migratedSpocs);
|
||||
|
||||
const {
|
||||
data: blockedResults,
|
||||
filtered: blocks,
|
||||
} = this.filterBlocked(capResult);
|
||||
blockedItems = [...blockedItems, ...blocks];
|
||||
const { data: blockedResults } = this.filterBlocked(capResult);
|
||||
|
||||
const {
|
||||
data: scoredResults,
|
||||
filtered: minScoreFilter,
|
||||
} = await this.scoreItems(blockedResults, "spocs");
|
||||
|
||||
belowMinScore = [...belowMinScore, ...minScoreFilter];
|
||||
const { data: scoredResults } = await this.scoreItems(
|
||||
blockedResults,
|
||||
"spocs"
|
||||
);
|
||||
|
||||
spocsState.spocs = {
|
||||
...spocsState.spocs,
|
||||
|
@ -813,14 +770,6 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
|
|||
lastUpdated: spocsState.lastUpdated,
|
||||
spocs: spocsState.spocs,
|
||||
});
|
||||
this._sendSpocsFill(
|
||||
{
|
||||
frequency_cap: frequencyCapped,
|
||||
blocked_by_user: blockedItems,
|
||||
below_min_score: belowMinScore,
|
||||
},
|
||||
true
|
||||
);
|
||||
} else {
|
||||
Cu.reportError("No response for spocs_endpoint prop");
|
||||
}
|
||||
|
@ -987,7 +936,6 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
|
|||
}
|
||||
|
||||
async scoreItems(items, type) {
|
||||
const filtered = [];
|
||||
const spocsPersonalized = this.store.getState().Prefs.values[
|
||||
PREF_SPOCS_PERSONALIZED
|
||||
];
|
||||
|
@ -1007,13 +955,12 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
|
|||
if (s.score >= s.min_score) {
|
||||
return true;
|
||||
}
|
||||
filtered.push(s);
|
||||
return false;
|
||||
})
|
||||
// Sort by highest scores.
|
||||
.sort(this.sortItem);
|
||||
|
||||
return { data, filtered };
|
||||
return { data };
|
||||
}
|
||||
|
||||
async scoreItem(item, personalizedByType) {
|
||||
|
@ -1029,24 +976,17 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
|
|||
}
|
||||
|
||||
filterBlocked(data) {
|
||||
const filtered = [];
|
||||
if (data && data.length) {
|
||||
let flights = this.readDataPref(PREF_FLIGHT_BLOCKS);
|
||||
const filteredItems = data.filter(item => {
|
||||
const blocked =
|
||||
NewTabUtils.blockedLinks.isBlocked({ url: item.url }) ||
|
||||
flights[item.flight_id];
|
||||
if (blocked) {
|
||||
filtered.push(item);
|
||||
}
|
||||
return !blocked;
|
||||
});
|
||||
return {
|
||||
data: filteredItems,
|
||||
filtered,
|
||||
};
|
||||
return { data: filteredItems };
|
||||
}
|
||||
return { data, filtered };
|
||||
return { data };
|
||||
}
|
||||
|
||||
// For backwards compatibility, older spoc endpoint don't have flight_id,
|
||||
|
@ -1320,7 +1260,6 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
|
|||
}
|
||||
|
||||
async scoreSpocs(spocsState) {
|
||||
let belowMinScore = [];
|
||||
const spocsResultPromises = this.getPlacements().map(async placement => {
|
||||
const nextSpocs = spocsState.data[placement.name] || {};
|
||||
const { items } = nextSpocs;
|
||||
|
@ -1329,12 +1268,7 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
|
|||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
data: scoreResult,
|
||||
filtered: minScoreFilter,
|
||||
} = await this.scoreItems(items, "spocs");
|
||||
|
||||
belowMinScore = [...belowMinScore, ...minScoreFilter];
|
||||
const { data: scoreResult } = await this.scoreItems(items, "spocs");
|
||||
|
||||
spocsState.data = {
|
||||
...spocsState.data,
|
||||
|
@ -1361,14 +1295,6 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
|
|||
},
|
||||
})
|
||||
);
|
||||
if (belowMinScore.length) {
|
||||
this._sendSpocsFill(
|
||||
{
|
||||
below_min_score: belowMinScore,
|
||||
},
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async refreshContent(options = {}) {
|
||||
|
@ -1735,7 +1661,6 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
|
|||
},
|
||||
})
|
||||
);
|
||||
this._sendSpocsFill({ frequency_cap: frequencyCapped }, false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1778,7 +1703,6 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
|
|||
spocs: spocsState.data,
|
||||
});
|
||||
|
||||
this._sendSpocsFill({ blocked_by_user: blockedItems }, false);
|
||||
// If we're blocking a spoc, we want open tabs to have
|
||||
// a slightly different treatment from future tabs.
|
||||
// AlsoToPreloaded updates the source data and preloaded tabs with a new spoc.
|
||||
|
|
|
@ -556,13 +556,6 @@ this.TelemetryFeed = class TelemetryFeed {
|
|||
});
|
||||
}
|
||||
|
||||
createSpocsFillPing(data) {
|
||||
return Object.assign(this.createPing(null), data, {
|
||||
impression_id: this._impressionId,
|
||||
session_id: "n/a",
|
||||
});
|
||||
}
|
||||
|
||||
createUserEvent(action) {
|
||||
return Object.assign(
|
||||
this.createPing(au.getPortIdOfSender(action)),
|
||||
|
@ -941,9 +934,6 @@ this.TelemetryFeed = class TelemetryFeed {
|
|||
action.data
|
||||
);
|
||||
break;
|
||||
case at.DISCOVERY_STREAM_SPOCS_FILL:
|
||||
this.handleDiscoveryStreamSpocsFill(action.data);
|
||||
break;
|
||||
case at.TELEMETRY_UNDESIRED_EVENT:
|
||||
this.handleUndesiredEvent(action);
|
||||
break;
|
||||
|
@ -1031,38 +1021,6 @@ this.TelemetryFeed = class TelemetryFeed {
|
|||
session.loadedContentSets = loadedContentSets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handl SPOCS Fill actions from Discovery Stream.
|
||||
*
|
||||
* @param {Object} data
|
||||
* The SPOCS Fill event structured as:
|
||||
* {
|
||||
* spoc_fills: [
|
||||
* {
|
||||
* id: 123,
|
||||
* displayed: 0,
|
||||
* reason: "frequency_cap",
|
||||
* full_recalc: 1
|
||||
* },
|
||||
* {
|
||||
* id: 124,
|
||||
* displayed: 1,
|
||||
* reason: "n/a",
|
||||
* full_recalc: 1
|
||||
* }
|
||||
* ]
|
||||
* }
|
||||
*/
|
||||
handleDiscoveryStreamSpocsFill(data) {
|
||||
const payload = this.createSpocsFillPing(data);
|
||||
this.sendStructuredIngestionEvent(
|
||||
payload,
|
||||
STRUCTURED_INGESTION_NAMESPACE_AS,
|
||||
"spoc-fills",
|
||||
"1"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Take all enumerable members of the data object and merge them into
|
||||
* the session.perf object for the given port, so that it is sent to the
|
||||
|
|
|
@ -189,29 +189,6 @@ export const ImpressionStatsPing = Joi.object().keys(
|
|||
})
|
||||
);
|
||||
|
||||
export const SpocsFillEntrySchema = Joi.object().keys({
|
||||
id: Joi.number()
|
||||
.integer()
|
||||
.required(),
|
||||
displayed: Joi.number()
|
||||
.integer()
|
||||
.required(),
|
||||
reason: Joi.string().required(),
|
||||
full_recalc: Joi.number()
|
||||
.integer()
|
||||
.required(),
|
||||
});
|
||||
|
||||
export const SpocsFillPing = Joi.object().keys(
|
||||
Object.assign({}, baseKeys, {
|
||||
impression_id: Joi.string().required(),
|
||||
session_id: Joi.valid("n/a").required(),
|
||||
spoc_fills: Joi.array()
|
||||
.items(SpocsFillEntrySchema)
|
||||
.required(),
|
||||
})
|
||||
);
|
||||
|
||||
export const SessionPing = Joi.object().keys(
|
||||
Object.assign({}, baseKeys, {
|
||||
session_id: baseKeys.session_id.required(),
|
||||
|
|
|
@ -37,13 +37,6 @@ describe("selectLayoutRender", () => {
|
|||
assert.deepEqual(layoutRender, []);
|
||||
});
|
||||
|
||||
it("should return an empty SPOCS fill array given initial state", () => {
|
||||
const { spocsFill } = selectLayoutRender({
|
||||
state: store.getState().DiscoveryStream,
|
||||
});
|
||||
assert.deepEqual(spocsFill, []);
|
||||
});
|
||||
|
||||
it("should add .data property from feeds to each compontent in .layout", () => {
|
||||
store.dispatch({
|
||||
type: at.DISCOVERY_STREAM_LAYOUT_UPDATE,
|
||||
|
@ -217,7 +210,7 @@ describe("selectLayoutRender", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("should return spoc result and spocs fill for rolls below the probability", () => {
|
||||
it("should return spoc result for rolls below the probability", () => {
|
||||
const fakeSpocConfig = {
|
||||
positions: [{ index: 0 }, { index: 1 }],
|
||||
probability: 0.5,
|
||||
|
@ -250,7 +243,7 @@ describe("selectLayoutRender", () => {
|
|||
});
|
||||
const randomStub = globals.sandbox.stub(global.Math, "random").returns(0.1);
|
||||
|
||||
const { spocsFill, layoutRender } = selectLayoutRender({
|
||||
const { layoutRender } = selectLayoutRender({
|
||||
state: store.getState().DiscoveryStream,
|
||||
});
|
||||
|
||||
|
@ -270,14 +263,9 @@ describe("selectLayoutRender", () => {
|
|||
assert.deepEqual(layoutRender[0].components[0].data.recommendations[3], {
|
||||
id: "bar",
|
||||
});
|
||||
|
||||
assert.deepEqual(spocsFill, [
|
||||
{ id: undefined, reason: "n/a", displayed: 1, full_recalc: 0 },
|
||||
{ id: undefined, reason: "n/a", displayed: 1, full_recalc: 0 },
|
||||
]);
|
||||
});
|
||||
|
||||
it("should return spoc result and spocs fill when there are more positions than spocs", () => {
|
||||
it("should return spoc result when there are more positions than spocs", () => {
|
||||
const fakeSpocConfig = {
|
||||
positions: [{ index: 0 }, { index: 1 }, { index: 2 }],
|
||||
probability: 0.5,
|
||||
|
@ -310,7 +298,7 @@ describe("selectLayoutRender", () => {
|
|||
});
|
||||
const randomStub = globals.sandbox.stub(global.Math, "random").returns(0.1);
|
||||
|
||||
const { spocsFill, layoutRender } = selectLayoutRender({
|
||||
const { layoutRender } = selectLayoutRender({
|
||||
state: store.getState().DiscoveryStream,
|
||||
});
|
||||
|
||||
|
@ -330,11 +318,6 @@ describe("selectLayoutRender", () => {
|
|||
assert.deepEqual(layoutRender[0].components[0].data.recommendations[3], {
|
||||
id: "bar",
|
||||
});
|
||||
|
||||
assert.deepEqual(spocsFill, [
|
||||
{ id: undefined, reason: "n/a", displayed: 1, full_recalc: 0 },
|
||||
{ id: undefined, reason: "n/a", displayed: 1, full_recalc: 0 },
|
||||
]);
|
||||
});
|
||||
|
||||
it("should report non-displayed spocs with reason as probability_selection and out_of_position", () => {
|
||||
|
@ -370,7 +353,7 @@ describe("selectLayoutRender", () => {
|
|||
});
|
||||
const randomStub = globals.sandbox.stub(global.Math, "random");
|
||||
|
||||
const { spocsFill, layoutRender } = selectLayoutRender({
|
||||
const { layoutRender } = selectLayoutRender({
|
||||
state: store.getState().DiscoveryStream,
|
||||
rollCache: [0.7, 0.3, 0.8],
|
||||
});
|
||||
|
@ -387,22 +370,6 @@ describe("selectLayoutRender", () => {
|
|||
assert.deepEqual(layoutRender[0].components[0].data.recommendations[2], {
|
||||
id: "bar",
|
||||
});
|
||||
|
||||
assert.deepEqual(spocsFill, [
|
||||
{ id: undefined, reason: "n/a", displayed: 1, full_recalc: 0 },
|
||||
{
|
||||
id: undefined,
|
||||
reason: "probability_selection",
|
||||
displayed: 0,
|
||||
full_recalc: 0,
|
||||
},
|
||||
{
|
||||
id: undefined,
|
||||
reason: "out_of_position",
|
||||
displayed: 0,
|
||||
full_recalc: 0,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("should not return spoc result for rolls above the probability", () => {
|
||||
|
@ -438,7 +405,7 @@ describe("selectLayoutRender", () => {
|
|||
});
|
||||
const randomStub = globals.sandbox.stub(global.Math, "random").returns(0.6);
|
||||
|
||||
const { spocsFill, layoutRender } = selectLayoutRender({
|
||||
const { layoutRender } = selectLayoutRender({
|
||||
state: store.getState().DiscoveryStream,
|
||||
});
|
||||
|
||||
|
@ -450,21 +417,6 @@ describe("selectLayoutRender", () => {
|
|||
assert.deepEqual(layoutRender[0].components[0].data.recommendations[1], {
|
||||
id: "bar",
|
||||
});
|
||||
|
||||
assert.deepEqual(spocsFill, [
|
||||
{
|
||||
id: undefined,
|
||||
reason: "probability_selection",
|
||||
displayed: 0,
|
||||
full_recalc: 0,
|
||||
},
|
||||
{
|
||||
id: undefined,
|
||||
reason: "out_of_position",
|
||||
displayed: 0,
|
||||
full_recalc: 0,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("Subsequent render should return spoc result for cached rolls below the probability", () => {
|
||||
|
@ -500,7 +452,7 @@ describe("selectLayoutRender", () => {
|
|||
});
|
||||
const randomStub = globals.sandbox.stub(global.Math, "random");
|
||||
|
||||
const { spocsFill, layoutRender } = selectLayoutRender({
|
||||
const { layoutRender } = selectLayoutRender({
|
||||
state: store.getState().DiscoveryStream,
|
||||
rollCache: [0.4, 0.3],
|
||||
});
|
||||
|
@ -521,11 +473,6 @@ describe("selectLayoutRender", () => {
|
|||
assert.deepEqual(layoutRender[0].components[0].data.recommendations[3], {
|
||||
id: "bar",
|
||||
});
|
||||
|
||||
assert.deepEqual(spocsFill, [
|
||||
{ id: undefined, reason: "n/a", displayed: 1, full_recalc: 0 },
|
||||
{ id: undefined, reason: "n/a", displayed: 1, full_recalc: 0 },
|
||||
]);
|
||||
});
|
||||
|
||||
it("Subsequent render should not return spoc result for cached rolls above the probability", () => {
|
||||
|
@ -561,7 +508,7 @@ describe("selectLayoutRender", () => {
|
|||
});
|
||||
const randomStub = globals.sandbox.stub(global.Math, "random");
|
||||
|
||||
const { spocsFill, layoutRender } = selectLayoutRender({
|
||||
const { layoutRender } = selectLayoutRender({
|
||||
state: store.getState().DiscoveryStream,
|
||||
rollCache: [0.6, 0.7],
|
||||
});
|
||||
|
@ -574,21 +521,6 @@ describe("selectLayoutRender", () => {
|
|||
assert.deepEqual(layoutRender[0].components[0].data.recommendations[1], {
|
||||
id: "bar",
|
||||
});
|
||||
|
||||
assert.deepEqual(spocsFill, [
|
||||
{
|
||||
id: undefined,
|
||||
reason: "probability_selection",
|
||||
displayed: 0,
|
||||
full_recalc: 0,
|
||||
},
|
||||
{
|
||||
id: undefined,
|
||||
reason: "out_of_position",
|
||||
displayed: 0,
|
||||
full_recalc: 0,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("Subsequent render should return spoc result by cached rolls probability", () => {
|
||||
|
@ -624,7 +556,7 @@ describe("selectLayoutRender", () => {
|
|||
});
|
||||
const randomStub = globals.sandbox.stub(global.Math, "random");
|
||||
|
||||
const { spocsFill, layoutRender } = selectLayoutRender({
|
||||
const { layoutRender } = selectLayoutRender({
|
||||
state: store.getState().DiscoveryStream,
|
||||
rollCache: [0.7, 0.2],
|
||||
});
|
||||
|
@ -641,16 +573,6 @@ describe("selectLayoutRender", () => {
|
|||
assert.deepEqual(layoutRender[0].components[0].data.recommendations[2], {
|
||||
id: "bar",
|
||||
});
|
||||
|
||||
assert.deepEqual(spocsFill, [
|
||||
{ id: undefined, reason: "n/a", displayed: 1, full_recalc: 0 },
|
||||
{
|
||||
id: undefined,
|
||||
reason: "out_of_position",
|
||||
displayed: 0,
|
||||
full_recalc: 0,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("should return a layout with feeds of items length with positions", () => {
|
||||
|
@ -681,7 +603,7 @@ describe("selectLayoutRender", () => {
|
|||
});
|
||||
store.dispatch({ type: at.DISCOVERY_STREAM_FEEDS_UPDATE });
|
||||
|
||||
const { spocsFill, layoutRender } = selectLayoutRender({
|
||||
const { layoutRender } = selectLayoutRender({
|
||||
state: store.getState().DiscoveryStream,
|
||||
});
|
||||
|
||||
|
@ -691,8 +613,6 @@ describe("selectLayoutRender", () => {
|
|||
assert.equal(recommendations[1].pos, 1);
|
||||
assert.equal(recommendations[2].pos, 2);
|
||||
assert.equal(recommendations[3].pos, undefined);
|
||||
|
||||
assert.lengthOf(spocsFill, 0);
|
||||
});
|
||||
it("should stop rendering feeds if we hit one that's not ready", () => {
|
||||
const fakeLayout = [
|
||||
|
|
|
@ -1234,7 +1234,7 @@ describe("DiscoveryStreamFeed", () => {
|
|||
});
|
||||
|
||||
it("should remove items with scores lower than min_score", async () => {
|
||||
const { data: result, filtered } = await feed.scoreItems([
|
||||
const { data: result } = await feed.scoreItems([
|
||||
{ id: 2, flight_id: 2, item_score: 0.8, min_score: 0.9 },
|
||||
{ id: 3, flight_id: 3, item_score: 0.7, min_score: 0.7 },
|
||||
{ id: 1, flight_id: 1, item_score: 0.9, min_score: 0.8 },
|
||||
|
@ -1244,10 +1244,6 @@ describe("DiscoveryStreamFeed", () => {
|
|||
{ id: 1, flight_id: 1, item_score: 0.9, score: 0.9, min_score: 0.8 },
|
||||
{ id: 3, flight_id: 3, item_score: 0.7, score: 0.7, min_score: 0.7 },
|
||||
]);
|
||||
|
||||
assert.deepEqual(filtered, [
|
||||
{ id: 2, flight_id: 2, item_score: 0.8, min_score: 0.9, score: 0.8 },
|
||||
]);
|
||||
});
|
||||
|
||||
it("should add a score prop to spocs", async () => {
|
||||
|
@ -1258,7 +1254,7 @@ describe("DiscoveryStreamFeed", () => {
|
|||
assert.equal(result[0].score, 0.9);
|
||||
});
|
||||
it("should score items using item_score and min_score", async () => {
|
||||
const { data: result, filtered } = await feed.scoreItems([
|
||||
const { data: result } = await feed.scoreItems([
|
||||
{ item_score: 0.8, min_score: 0.1 },
|
||||
{ item_score: 0.5, min_score: 0.6 },
|
||||
{ item_score: 0.7, min_score: 0.1 },
|
||||
|
@ -1269,9 +1265,6 @@ describe("DiscoveryStreamFeed", () => {
|
|||
{ item_score: 0.8, score: 0.8, min_score: 0.1 },
|
||||
{ item_score: 0.7, score: 0.7, min_score: 0.1 },
|
||||
]);
|
||||
assert.deepEqual(filtered, [
|
||||
{ item_score: 0.5, min_score: 0.6, score: 0.5 },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1288,21 +1281,6 @@ describe("DiscoveryStreamFeed", () => {
|
|||
]);
|
||||
assert.equal(result.length, 2);
|
||||
});
|
||||
it("should return filtered out based on blockedlist", () => {
|
||||
fakeNewTabUtils.blockedLinks.links = [{ url: "https://foo.com" }];
|
||||
fakeNewTabUtils.blockedLinks.isBlocked = site =>
|
||||
fakeNewTabUtils.blockedLinks.links[0].url === site.url;
|
||||
|
||||
const { data: result, filtered } = feed.filterBlocked([
|
||||
{ id: 1, url: "https://foo.com" },
|
||||
{ id: 2, url: "test.com" },
|
||||
]);
|
||||
|
||||
assert.lengthOf(result, 1);
|
||||
assert.equal(result[0].url, "test.com");
|
||||
assert.notInclude(result, fakeNewTabUtils.blockedLinks.links[0]);
|
||||
assert.deepEqual(filtered, [{ id: 1, url: "https://foo.com" }]);
|
||||
});
|
||||
it("should return initial recommendations data if links are not blocked", () => {
|
||||
const { data: result } = feed.filterBlocked([
|
||||
{ url: "https://foo.com" },
|
||||
|
@ -1767,15 +1745,6 @@ describe("DiscoveryStreamFeed", () => {
|
|||
],
|
||||
},
|
||||
};
|
||||
const spocFillResult = [
|
||||
{
|
||||
id: 1,
|
||||
reason: "frequency_cap",
|
||||
displayed: 0,
|
||||
full_recalc: 0,
|
||||
},
|
||||
];
|
||||
|
||||
sandbox.stub(feed, "recordFlightImpression").returns();
|
||||
sandbox.stub(feed, "readDataPref").returns(fakeImpressions);
|
||||
sandbox.spy(feed.store, "dispatch");
|
||||
|
@ -1789,10 +1758,6 @@ describe("DiscoveryStreamFeed", () => {
|
|||
feed.store.dispatch.secondCall.args[0].data.spocs,
|
||||
result
|
||||
);
|
||||
assert.deepEqual(
|
||||
feed.store.dispatch.thirdCall.args[0].data.spoc_fills,
|
||||
spocFillResult
|
||||
);
|
||||
});
|
||||
it("should not call dispatch to ac.AlsoToPreloaded if spocs were not changed by frequency capping", async () => {
|
||||
Object.defineProperty(feed, "showSpocs", { get: () => true });
|
||||
|
@ -1881,16 +1846,8 @@ describe("DiscoveryStreamFeed", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("should call dispatch with the SPOCS Fill if found a blocked spoc", async () => {
|
||||
it("should call dispatch if found a blocked spoc", async () => {
|
||||
Object.defineProperty(feed, "showSpocs", { get: () => true });
|
||||
const spocFillResult = [
|
||||
{
|
||||
id: 1,
|
||||
reason: "blocked_by_user",
|
||||
displayed: 0,
|
||||
full_recalc: 0,
|
||||
},
|
||||
];
|
||||
|
||||
sandbox.spy(feed.store, "dispatch");
|
||||
|
||||
|
@ -1900,15 +1857,11 @@ describe("DiscoveryStreamFeed", () => {
|
|||
});
|
||||
|
||||
assert.deepEqual(
|
||||
feed.store.dispatch.firstCall.args[0].data.spoc_fills,
|
||||
spocFillResult
|
||||
);
|
||||
assert.deepEqual(
|
||||
feed.store.dispatch.secondCall.args[0].data.url,
|
||||
feed.store.dispatch.firstCall.args[0].data.url,
|
||||
"foo.com"
|
||||
);
|
||||
});
|
||||
it("should not call dispatch with the SPOCS Fill if the blocked is not a SPOC", async () => {
|
||||
it("should dispatch once if the blocked is not a SPOC", async () => {
|
||||
Object.defineProperty(feed, "showSpocs", { get: () => true });
|
||||
sandbox.spy(feed.store, "dispatch");
|
||||
|
||||
|
@ -1933,7 +1886,7 @@ describe("DiscoveryStreamFeed", () => {
|
|||
});
|
||||
|
||||
assert.equal(
|
||||
feed.store.dispatch.thirdCall.args[0].type,
|
||||
feed.store.dispatch.secondCall.args[0].type,
|
||||
"DISCOVERY_STREAM_SPOC_BLOCKED"
|
||||
);
|
||||
});
|
||||
|
@ -2677,10 +2630,9 @@ describe("DiscoveryStreamFeed", () => {
|
|||
});
|
||||
|
||||
describe("#scoreSpocs", () => {
|
||||
it("should score spocs and set cache, dispatch, and spocsFill", async () => {
|
||||
it("should score spocs and set cache, dispatch", async () => {
|
||||
sandbox.stub(feed.cache, "set").resolves();
|
||||
sandbox.spy(feed.store, "dispatch");
|
||||
sandbox.stub(feed, "_sendSpocsFill").returns();
|
||||
const fakeDiscoveryStream = {
|
||||
Prefs: {
|
||||
values: {
|
||||
|
@ -2779,13 +2731,6 @@ describe("DiscoveryStreamFeed", () => {
|
|||
feed.store.dispatch.firstCall.args[0].data,
|
||||
spocsTestResult
|
||||
);
|
||||
assert.calledWith(
|
||||
feed._sendSpocsFill,
|
||||
{
|
||||
below_min_score: [{ item_score: 0.4, min_score: 0.5, score: 0.4 }],
|
||||
},
|
||||
false
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -2892,7 +2837,7 @@ describe("DiscoveryStreamFeed", () => {
|
|||
});
|
||||
describe("#scoreItems", () => {
|
||||
it("should score items using item_score and min_score", async () => {
|
||||
const { data: result, filtered } = await feed.scoreItems([
|
||||
const { data: result } = await feed.scoreItems([
|
||||
{ item_score: 0.8, min_score: 0.1 },
|
||||
{ item_score: 0.5, min_score: 0.6 },
|
||||
{ item_score: 0.7, min_score: 0.1 },
|
||||
|
@ -2903,9 +2848,6 @@ describe("DiscoveryStreamFeed", () => {
|
|||
{ item_score: 0.8, score: 0.8, min_score: 0.1 },
|
||||
{ item_score: 0.7, score: 0.7, min_score: 0.1 },
|
||||
]);
|
||||
assert.deepEqual(filtered, [
|
||||
{ item_score: 0.5, min_score: 0.6, score: 0.5 },
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe("#scoreItem", () => {
|
||||
|
@ -2945,84 +2887,4 @@ describe("DiscoveryStreamFeed", () => {
|
|||
assert.equal(result.min_score, 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#_sendSpocsFill", () => {
|
||||
it("should send out all the SPOCS Fill pings", () => {
|
||||
sandbox.spy(feed.store, "dispatch");
|
||||
const expected = [
|
||||
{ id: 1, reason: "frequency_cap", displayed: 0, full_recalc: 1 },
|
||||
{ id: 2, reason: "frequency_cap", displayed: 0, full_recalc: 1 },
|
||||
{ id: 3, reason: "blocked_by_user", displayed: 0, full_recalc: 1 },
|
||||
{ id: 4, reason: "blocked_by_user", displayed: 0, full_recalc: 1 },
|
||||
{ id: 5, reason: "flight_duplicate", displayed: 0, full_recalc: 1 },
|
||||
{ id: 6, reason: "flight_duplicate", displayed: 0, full_recalc: 1 },
|
||||
{ id: 7, reason: "below_min_score", displayed: 0, full_recalc: 1 },
|
||||
{ id: 8, reason: "below_min_score", displayed: 0, full_recalc: 1 },
|
||||
];
|
||||
const filtered = {
|
||||
frequency_cap: [
|
||||
{ id: 1, flight_id: 1 },
|
||||
{ id: 2, flight_id: 2 },
|
||||
],
|
||||
blocked_by_user: [
|
||||
{ id: 3, flight_id: 3 },
|
||||
{ id: 4, flight_id: 4 },
|
||||
],
|
||||
flight_duplicate: [
|
||||
{ id: 5, flight_id: 5 },
|
||||
{ id: 6, flight_id: 6 },
|
||||
],
|
||||
below_min_score: [
|
||||
{ id: 7, flight_id: 7 },
|
||||
{ id: 8, flight_id: 8 },
|
||||
],
|
||||
};
|
||||
feed._sendSpocsFill(filtered, true);
|
||||
|
||||
assert.deepEqual(
|
||||
feed.store.dispatch.firstCall.args[0].data.spoc_fills,
|
||||
expected
|
||||
);
|
||||
});
|
||||
it("should send SPOCS Fill ping with the correct full_recalc", () => {
|
||||
sandbox.spy(feed.store, "dispatch");
|
||||
const expected = [
|
||||
{ id: 1, reason: "frequency_cap", displayed: 0, full_recalc: 0 },
|
||||
{ id: 2, reason: "frequency_cap", displayed: 0, full_recalc: 0 },
|
||||
];
|
||||
const filtered = {
|
||||
frequency_cap: [
|
||||
{ id: 1, flight_id: 1 },
|
||||
{ id: 2, flight_id: 2 },
|
||||
],
|
||||
};
|
||||
feed._sendSpocsFill(filtered, false);
|
||||
|
||||
assert.deepEqual(
|
||||
feed.store.dispatch.firstCall.args[0].data.spoc_fills,
|
||||
expected
|
||||
);
|
||||
});
|
||||
it("should not send non-SPOCS Fill pings", () => {
|
||||
sandbox.spy(feed.store, "dispatch");
|
||||
const expected = [
|
||||
{ id: 1, reason: "frequency_cap", displayed: 0, full_recalc: 1 },
|
||||
{ id: 3, reason: "blocked_by_user", displayed: 0, full_recalc: 1 },
|
||||
{ id: 5, reason: "flight_duplicate", displayed: 0, full_recalc: 1 },
|
||||
{ id: 7, reason: "below_min_score", displayed: 0, full_recalc: 1 },
|
||||
];
|
||||
const filtered = {
|
||||
frequency_cap: [{ id: 1, flight_id: 1 }, { id: 2 }],
|
||||
blocked_by_user: [{ id: 3, flight_id: 3 }, { id: 4 }],
|
||||
flight_duplicate: [{ id: 5, flight_id: 5 }, { id: 6 }],
|
||||
below_min_score: [{ id: 7, flight_id: 7 }, { id: 8 }],
|
||||
};
|
||||
feed._sendSpocsFill(filtered, true);
|
||||
|
||||
assert.deepEqual(
|
||||
feed.store.dispatch.firstCall.args[0].data.spoc_fills,
|
||||
expected
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -9,7 +9,6 @@ import {
|
|||
BasePing,
|
||||
ImpressionStatsPing,
|
||||
SessionPing,
|
||||
SpocsFillPing,
|
||||
UndesiredPing,
|
||||
UserEventPing,
|
||||
} from "test/schemas/pings";
|
||||
|
@ -731,20 +730,6 @@ describe("TelemetryFeed", () => {
|
|||
assert.propertyVal(ping.tiles[0], "shim", tiles[0].shim);
|
||||
});
|
||||
});
|
||||
describe("#createSpocsFillPing", () => {
|
||||
it("should create a valid SPOCS Fill ping", async () => {
|
||||
const spocFills = [
|
||||
{ id: 10001, displayed: 0, reason: "frequency_cap", full_recalc: 1 },
|
||||
{ id: 10002, displayed: 0, reason: "blocked_by_user", full_recalc: 1 },
|
||||
{ id: 10003, displayed: 1, reason: "n/a", full_recalc: 1 },
|
||||
];
|
||||
const action = ac.DiscoveryStreamSpocsFill({ spoc_fills: spocFills });
|
||||
const ping = await instance.createSpocsFillPing(action.data);
|
||||
|
||||
assert.validate(ping, SpocsFillPing);
|
||||
assert.propertyVal(ping, "spoc_fills", spocFills);
|
||||
});
|
||||
});
|
||||
describe("#applyCFRPolicy", () => {
|
||||
it("should use client_id and message_id in prerelease", async () => {
|
||||
globals.set("UpdateUtils", {
|
||||
|
@ -1520,21 +1505,6 @@ describe("TelemetryFeed", () => {
|
|||
data
|
||||
);
|
||||
});
|
||||
it("should send an event on a DISCOVERY_STREAM_SPOCS_FILL action", () => {
|
||||
const sendEvent = sandbox.stub(instance, "sendStructuredIngestionEvent");
|
||||
const eventCreator = sandbox.stub(instance, "createSpocsFillPing");
|
||||
const spocFills = [
|
||||
{ id: 10001, displayed: 0, reason: "frequency_cap", full_recalc: 1 },
|
||||
{ id: 10002, displayed: 0, reason: "blocked_by_user", full_recalc: 1 },
|
||||
{ id: 10003, displayed: 1, reason: "n/a", full_recalc: 1 },
|
||||
];
|
||||
const action = ac.DiscoveryStreamSpocsFill({ spoc_fills: spocFills });
|
||||
|
||||
instance.onAction(action);
|
||||
|
||||
assert.calledWith(eventCreator, action.data);
|
||||
assert.calledWith(sendEvent, eventCreator.returnValue);
|
||||
});
|
||||
});
|
||||
describe("#handleNewTabInit", () => {
|
||||
it("should set the session as preloaded if the browser is preloaded", () => {
|
||||
|
|
Загрузка…
Ссылка в новой задаче