Bug 1550300 - Add top source, unblank discovery and bug fixes to Activity Stream r=r1cky

Differential Revision: https://phabricator.services.mozilla.com/D30438

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Ed Lee 2019-05-09 01:42:56 +00:00
Родитель 3fb822b110
Коммит de6f8d5227
31 изменённых файлов: 316 добавлений и 102 удалений

Просмотреть файл

@ -132,6 +132,7 @@ for (const type of [
"TOP_SITES_UPDATED",
"TOTAL_BOOKMARKS_REQUEST",
"TOTAL_BOOKMARKS_RESPONSE",
"TRAILHEAD_ENROLL_EVENT",
"UNINIT",
"UPDATE_PINNED_SEARCH_SHORTCUTS",
"UPDATE_SEARCH_SHORTCUTS",

Просмотреть файл

@ -8,7 +8,7 @@ export class ModalOverlayWrapper extends React.PureComponent {
onKeyDown(event) {
if (event.key === "Escape") {
this.props.onClose();
this.props.onClose(event);
}
}

Просмотреть файл

@ -123,13 +123,18 @@ export class _Trailhead extends React.PureComponent {
global.addEventListener("visibilitychange", this.closeModal);
}
closeModal() {
closeModal(ev) {
global.removeEventListener("visibilitychange", this.closeModal);
this.props.document.body.classList.remove("welcome");
this.props.document.getElementById("root").removeAttribute("aria-hidden");
this.setState({isModalOpen: false});
this.revealCards();
this.props.dispatch(ac.UserEvent({event: "SKIPPED_SIGNIN", ...this._getFormInfo()}));
// If closeModal() was triggered by a visibilitychange event, the user actually
// submitted the email form so we don't send a SKIPPED_SIGNIN ping.
if (!ev || ev.type !== "visibilitychange") {
this.props.dispatch(ac.UserEvent({event: "SKIPPED_SIGNIN", ...this._getFormInfo()}));
}
}
/**
@ -223,7 +228,7 @@ export class _Trailhead extends React.PureComponent {
</li>
))}
</ul>
<a className="trailheadLearn" data-l10n-id={content.learn.text.string_id} href={this.addUtmParams(content.learn.url)}>
<a className="trailheadLearn" data-l10n-id={content.learn.text.string_id} href={this.addUtmParams(content.learn.url)} target="_blank" rel="noopener noreferrer">
{this.getStringValue(content.learn.text)}
</a>
</div>
@ -247,13 +252,13 @@ export class _Trailhead extends React.PureComponent {
placeholder={this.getStringValue(content.form.email)}
name="email"
type="email"
required="true"
required="required"
onInvalid={this.onInputInvalid}
onChange={this.onInputChange} />
<p className="trailheadTerms" data-l10n-id="onboarding-join-form-legal">
<a data-l10n-name="terms"
<a data-l10n-name="terms" target="_blank" rel="noopener noreferrer"
href={this.addUtmParams("https://accounts.firefox.com/legal/terms")} />
<a data-l10n-name="privacy"
<a data-l10n-name="privacy" target="_blank" rel="noopener noreferrer"
href={this.addUtmParams("https://accounts.firefox.com/legal/privacy")} />
</p>
<button data-l10n-id={content.form.button.string_id} type="submit">

Просмотреть файл

@ -63,7 +63,7 @@
.trailheadContent {
.trailheadBenefits {
background: url('#{$image-path}sync-devices.svg');
background: url('#{$image-path}sync-devices-trailhead.svg');
background-position: center center;
background-repeat: no-repeat;
background-size: contain;
@ -401,6 +401,14 @@
}
.inline-onboarding {
&.activity-stream.welcome {
overflow: scroll;
}
.modalOverlayInner {
position: absolute;
}
.outer-wrapper {
position: relative;
@ -415,15 +423,3 @@
position: absolute;
}
}
// If the window is too short or narrow, we need to allow scrolling so user can get to Start Browsing button.
@media (max-height: 760px), (max-width: 924px) {
.activity-stream.welcome.inline-onboarding {
overflow: auto;
}
.trailhead {
position: absolute;
top: 20px;
}
}

Просмотреть файл

@ -41,18 +41,13 @@ export class DSCard extends React.PureComponent {
</div>
<div className="meta">
<div className="info-wrap">
<p className="source">{this.props.source}</p>
<header className="title">{this.props.title}</header>
{this.props.excerpt && <p className="excerpt">{this.props.excerpt}</p>}
</div>
<p>
{this.props.context && (
<span>
<span className="context">{this.props.context}</span>
<br />
</span>
)}
<span className="source">{this.props.source}</span>
</p>
{this.props.context && (
<p className="context">{this.props.context}</p>
)}
</div>
<ImpressionStats
campaignId={this.props.campaignId}

Просмотреть файл

@ -90,6 +90,10 @@ $excerpt-line-height: 20;
@include limit-visibile-lines(3, $excerpt-line-height, $excerpt-font-size);
}
.source {
margin-bottom: 2px;
}
.context,
.source {
@include dark-theme-only {

Просмотреть файл

@ -81,14 +81,14 @@ export class Hero extends React.PureComponent {
</div>
<div className="meta">
<div className="header-and-excerpt">
{heroRec.context ? (
<p className="context">{heroRec.context}</p>
) : (
<p className="source">{heroRec.domain}</p>
)}
<header>{heroRec.title}</header>
<p className="excerpt">{heroRec.excerpt}</p>
</div>
{heroRec.context ? (
<p className="context">{heroRec.context}</p>
) : (
<p className="source">{heroRec.domain}</p>
)}
</div>
<ImpressionStats
campaignId={heroRec.campaignId}

Просмотреть файл

@ -127,6 +127,11 @@ $card-header-in-hero-line-height: 20;
margin-bottom: 0;
}
.context,
.source {
margin: 0 0 4px;
}
.context {
@include dark-theme-only {
color: $teal-10;

Просмотреть файл

@ -99,13 +99,13 @@ export const selectLayoutRender = (state, prefs, rickRollCache) => {
const renderLayout = () => {
const renderedLayoutArray = [];
for (const row of layout.filter(r => r.components.length)) {
for (const row of layout.filter(r => r.components.filter(c => !filterArray.includes(c.type)).length)) {
let components = [];
renderedLayoutArray.push({
...row,
components,
});
for (const component of row.components.filter(c => !filterArray.includes(c.type))) {
for (const component of row.components) {
if (component.feed) {
const spocsConfig = component.spocs;
// Are we still waiting on a feed/spocs, render what we have, and bail out early.

Просмотреть файл

@ -2038,6 +2038,9 @@ main {
margin-bottom: 0; }
[lwt-newtab-brighttext] .ds-hero .wrapper .meta header {
color: #FFF; }
.ds-hero .wrapper .meta .context,
.ds-hero .wrapper .meta .source {
margin: 0 0 4px; }
.ds-hero .wrapper .meta .context {
color: #008EA4; }
[lwt-newtab-brighttext] .ds-hero .wrapper .meta .context {
@ -2643,6 +2646,8 @@ main {
line-height: 20px;
max-height: 4.28571em;
overflow: hidden; }
.ds-card .meta .source {
margin-bottom: 2px; }
.ds-card .meta .context,
.ds-card .meta .source {
font-size: 13px;
@ -3746,7 +3751,7 @@ a.firstrun-link {
.trailhead.syncCohort .trailheadInner {
grid-template-columns: 4fr 3fr; }
.trailhead.syncCohort .trailheadContent .trailheadBenefits {
background: url("../data/content/assets/sync-devices.svg");
background: url("../data/content/assets/sync-devices-trailhead.svg");
background-position: center center;
background-repeat: no-repeat;
background-size: contain;
@ -3970,6 +3975,12 @@ a.firstrun-link {
width: 100%;
text-align: center; }
.inline-onboarding.activity-stream.welcome {
overflow: scroll; }
.inline-onboarding .modalOverlayInner {
position: absolute; }
.inline-onboarding .outer-wrapper {
position: relative; }
.inline-onboarding .outer-wrapper .prefs-button button {
@ -3977,10 +3988,3 @@ a.firstrun-link {
.inline-onboarding .asrouter-toggle {
position: absolute; }
@media (max-height: 760px), (max-width: 924px) {
.activity-stream.welcome.inline-onboarding {
overflow: auto; }
.trailhead {
position: absolute;
top: 20px; } }

Просмотреть файл

@ -2041,6 +2041,9 @@ main {
margin-bottom: 0; }
[lwt-newtab-brighttext] .ds-hero .wrapper .meta header {
color: #FFF; }
.ds-hero .wrapper .meta .context,
.ds-hero .wrapper .meta .source {
margin: 0 0 4px; }
.ds-hero .wrapper .meta .context {
color: #008EA4; }
[lwt-newtab-brighttext] .ds-hero .wrapper .meta .context {
@ -2646,6 +2649,8 @@ main {
line-height: 20px;
max-height: 4.28571em;
overflow: hidden; }
.ds-card .meta .source {
margin-bottom: 2px; }
.ds-card .meta .context,
.ds-card .meta .source {
font-size: 13px;
@ -3749,7 +3754,7 @@ a.firstrun-link {
.trailhead.syncCohort .trailheadInner {
grid-template-columns: 4fr 3fr; }
.trailhead.syncCohort .trailheadContent .trailheadBenefits {
background: url("../data/content/assets/sync-devices.svg");
background: url("../data/content/assets/sync-devices-trailhead.svg");
background-position: center center;
background-repeat: no-repeat;
background-size: contain;
@ -3973,6 +3978,12 @@ a.firstrun-link {
width: 100%;
text-align: center; }
.inline-onboarding.activity-stream.welcome {
overflow: scroll; }
.inline-onboarding .modalOverlayInner {
position: absolute; }
.inline-onboarding .outer-wrapper {
position: relative; }
.inline-onboarding .outer-wrapper .prefs-button button {
@ -3980,10 +3991,3 @@ a.firstrun-link {
.inline-onboarding .asrouter-toggle {
position: absolute; }
@media (max-height: 760px), (max-width: 924px) {
.activity-stream.welcome.inline-onboarding {
overflow: auto; }
.trailhead {
position: absolute;
top: 20px; } }

Просмотреть файл

@ -2038,6 +2038,9 @@ main {
margin-bottom: 0; }
[lwt-newtab-brighttext] .ds-hero .wrapper .meta header {
color: #FFF; }
.ds-hero .wrapper .meta .context,
.ds-hero .wrapper .meta .source {
margin: 0 0 4px; }
.ds-hero .wrapper .meta .context {
color: #008EA4; }
[lwt-newtab-brighttext] .ds-hero .wrapper .meta .context {
@ -2643,6 +2646,8 @@ main {
line-height: 20px;
max-height: 4.28571em;
overflow: hidden; }
.ds-card .meta .source {
margin-bottom: 2px; }
.ds-card .meta .context,
.ds-card .meta .source {
font-size: 13px;
@ -3746,7 +3751,7 @@ a.firstrun-link {
.trailhead.syncCohort .trailheadInner {
grid-template-columns: 4fr 3fr; }
.trailhead.syncCohort .trailheadContent .trailheadBenefits {
background: url("../data/content/assets/sync-devices.svg");
background: url("../data/content/assets/sync-devices-trailhead.svg");
background-position: center center;
background-repeat: no-repeat;
background-size: contain;
@ -3970,6 +3975,12 @@ a.firstrun-link {
width: 100%;
text-align: center; }
.inline-onboarding.activity-stream.welcome {
overflow: scroll; }
.inline-onboarding .modalOverlayInner {
position: absolute; }
.inline-onboarding .outer-wrapper {
position: relative; }
.inline-onboarding .outer-wrapper .prefs-button button {
@ -3977,10 +3988,3 @@ a.firstrun-link {
.inline-onboarding .asrouter-toggle {
position: absolute; }
@media (max-height: 760px), (max-width: 924px) {
.activity-stream.welcome.inline-onboarding {
overflow: auto; }
.trailhead {
position: absolute;
top: 20px; } }

Просмотреть файл

@ -197,7 +197,7 @@ const globalImportContext = typeof Window === "undefined" ? BACKGROUND_PROCESS :
// }
const actionTypes = {};
for (const type of ["ADDONS_INFO_REQUEST", "ADDONS_INFO_RESPONSE", "ARCHIVE_FROM_POCKET", "AS_ROUTER_INITIALIZED", "AS_ROUTER_PREF_CHANGED", "AS_ROUTER_TELEMETRY_USER_EVENT", "BLOCK_URL", "BOOKMARK_URL", "COPY_DOWNLOAD_LINK", "DELETE_BOOKMARK_BY_ID", "DELETE_FROM_POCKET", "DELETE_HISTORY_URL", "DIALOG_CANCEL", "DIALOG_OPEN", "DISCOVERY_STREAM_CONFIG_CHANGE", "DISCOVERY_STREAM_CONFIG_SETUP", "DISCOVERY_STREAM_CONFIG_SET_VALUE", "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_OPT_OUT", "DISCOVERY_STREAM_SPOCS_CAPS", "DISCOVERY_STREAM_SPOCS_ENDPOINT", "DISCOVERY_STREAM_SPOCS_FILL", "DISCOVERY_STREAM_SPOCS_UPDATE", "DISCOVERY_STREAM_SPOC_IMPRESSION", "DOWNLOAD_CHANGED", "FAKE_FOCUS_SEARCH", "FILL_SEARCH_TERM", "HANDOFF_SEARCH_TO_AWESOMEBAR", "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", "PAGE_PRERENDERED", "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_SEARCH", "SKIPPED_SIGNIN", "SNIPPETS_BLOCKLIST_CLEARED", "SNIPPETS_BLOCKLIST_UPDATED", "SNIPPETS_DATA", "SNIPPETS_PREVIEW_MODE", "SNIPPETS_RESET", "SNIPPET_BLOCKED", "SUBMIT_EMAIL", "SYSTEM_TICK", "TELEMETRY_IMPRESSION_STATS", "TELEMETRY_PERFORMANCE_EVENT", "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 ["ADDONS_INFO_REQUEST", "ADDONS_INFO_RESPONSE", "ARCHIVE_FROM_POCKET", "AS_ROUTER_INITIALIZED", "AS_ROUTER_PREF_CHANGED", "AS_ROUTER_TELEMETRY_USER_EVENT", "BLOCK_URL", "BOOKMARK_URL", "COPY_DOWNLOAD_LINK", "DELETE_BOOKMARK_BY_ID", "DELETE_FROM_POCKET", "DELETE_HISTORY_URL", "DIALOG_CANCEL", "DIALOG_OPEN", "DISCOVERY_STREAM_CONFIG_CHANGE", "DISCOVERY_STREAM_CONFIG_SETUP", "DISCOVERY_STREAM_CONFIG_SET_VALUE", "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_OPT_OUT", "DISCOVERY_STREAM_SPOCS_CAPS", "DISCOVERY_STREAM_SPOCS_ENDPOINT", "DISCOVERY_STREAM_SPOCS_FILL", "DISCOVERY_STREAM_SPOCS_UPDATE", "DISCOVERY_STREAM_SPOC_IMPRESSION", "DOWNLOAD_CHANGED", "FAKE_FOCUS_SEARCH", "FILL_SEARCH_TERM", "HANDOFF_SEARCH_TO_AWESOMEBAR", "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", "PAGE_PRERENDERED", "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_SEARCH", "SKIPPED_SIGNIN", "SNIPPETS_BLOCKLIST_CLEARED", "SNIPPETS_BLOCKLIST_UPDATED", "SNIPPETS_DATA", "SNIPPETS_PREVIEW_MODE", "SNIPPETS_RESET", "SNIPPET_BLOCKED", "SUBMIT_EMAIL", "SYSTEM_TICK", "TELEMETRY_IMPRESSION_STATS", "TELEMETRY_PERFORMANCE_EVENT", "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", "TRAILHEAD_ENROLL_EVENT", "UNINIT", "UPDATE_PINNED_SEARCH_SHORTCUTS", "UPDATE_SEARCH_SHORTCUTS", "UPDATE_SECTION_PREFS", "WEBEXT_CLICK", "WEBEXT_DISMISS"]) {
actionTypes[type] = type;
} // These are acceptable actions for AS Router messages to have. They can show up
// as call-to-action buttons in snippets, onboarding tour, etc.
@ -2707,7 +2707,7 @@ class ModalOverlayWrapper extends react__WEBPACK_IMPORTED_MODULE_0___default.a.P
onKeyDown(event) {
if (event.key === "Escape") {
this.props.onClose();
this.props.onClose(event);
}
}
@ -3417,18 +3417,22 @@ class _Trailhead extends react__WEBPACK_IMPORTED_MODULE_4___default.a.PureCompon
global.addEventListener("visibilitychange", this.closeModal);
}
closeModal() {
closeModal(ev) {
global.removeEventListener("visibilitychange", this.closeModal);
this.props.document.body.classList.remove("welcome");
this.props.document.getElementById("root").removeAttribute("aria-hidden");
this.setState({
isModalOpen: false
});
this.revealCards();
this.props.dispatch(common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__["actionCreators"].UserEvent({
event: "SKIPPED_SIGNIN",
...this._getFormInfo()
}));
this.revealCards(); // If closeModal() was triggered by a visibilitychange event, the user actually
// submitted the email form so we don't send a SKIPPED_SIGNIN ping.
if (!ev || ev.type !== "visibilitychange") {
this.props.dispatch(common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__["actionCreators"].UserEvent({
event: "SKIPPED_SIGNIN",
...this._getFormInfo()
}));
}
}
/**
* Report to telemetry additional information about the form submission.
@ -3556,7 +3560,9 @@ class _Trailhead extends react__WEBPACK_IMPORTED_MODULE_4___default.a.PureCompon
}, this.getStringValue(item.text))))), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("a", {
className: "trailheadLearn",
"data-l10n-id": content.learn.text.string_id,
href: this.addUtmParams(content.learn.url)
href: this.addUtmParams(content.learn.url),
target: "_blank",
rel: "noopener noreferrer"
}, this.getStringValue(content.learn.text))), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("div", {
className: "trailheadForm"
}, react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("h3", {
@ -3617,7 +3623,7 @@ class _Trailhead extends react__WEBPACK_IMPORTED_MODULE_4___default.a.PureCompon
placeholder: this.getStringValue(content.form.email),
name: "email",
type: "email",
required: "true",
required: "required",
onInvalid: this.onInputInvalid,
onChange: this.onInputChange
}), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("p", {
@ -3625,9 +3631,13 @@ class _Trailhead extends react__WEBPACK_IMPORTED_MODULE_4___default.a.PureCompon
"data-l10n-id": "onboarding-join-form-legal"
}, react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("a", {
"data-l10n-name": "terms",
target: "_blank",
rel: "noopener noreferrer",
href: this.addUtmParams("https://accounts.firefox.com/legal/terms")
}), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("a", {
"data-l10n-name": "privacy",
target: "_blank",
rel: "noopener noreferrer",
href: this.addUtmParams("https://accounts.firefox.com/legal/privacy")
})), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("button", {
"data-l10n-id": content.form.button.string_id,
@ -7907,15 +7917,15 @@ class DSCard_DSCard extends external_React_default.a.PureComponent {
className: "meta"
}, external_React_default.a.createElement("div", {
className: "info-wrap"
}, external_React_default.a.createElement("header", {
}, external_React_default.a.createElement("p", {
className: "source"
}, this.props.source), external_React_default.a.createElement("header", {
className: "title"
}, this.props.title), this.props.excerpt && external_React_default.a.createElement("p", {
className: "excerpt"
}, this.props.excerpt)), external_React_default.a.createElement("p", null, this.props.context && external_React_default.a.createElement("span", null, external_React_default.a.createElement("span", {
}, this.props.excerpt)), this.props.context && external_React_default.a.createElement("p", {
className: "context"
}, this.props.context), external_React_default.a.createElement("br", null)), external_React_default.a.createElement("span", {
className: "source"
}, this.props.source))), external_React_default.a.createElement(ImpressionStats["ImpressionStats"], {
}, this.props.context)), external_React_default.a.createElement(ImpressionStats["ImpressionStats"], {
campaignId: this.props.campaignId,
rows: [{
id: this.props.id,
@ -8295,13 +8305,13 @@ class Hero_Hero extends external_React_default.a.PureComponent {
className: "meta"
}, external_React_default.a.createElement("div", {
className: "header-and-excerpt"
}, external_React_default.a.createElement("header", null, heroRec.title), external_React_default.a.createElement("p", {
className: "excerpt"
}, heroRec.excerpt)), heroRec.context ? external_React_default.a.createElement("p", {
}, heroRec.context ? external_React_default.a.createElement("p", {
className: "context"
}, heroRec.context) : external_React_default.a.createElement("p", {
className: "source"
}, heroRec.domain)), external_React_default.a.createElement(ImpressionStats["ImpressionStats"], {
}, heroRec.domain), external_React_default.a.createElement("header", null, heroRec.title), external_React_default.a.createElement("p", {
className: "excerpt"
}, heroRec.excerpt))), external_React_default.a.createElement(ImpressionStats["ImpressionStats"], {
campaignId: heroRec.campaignId,
rows: [{
id: heroRec.id,
@ -8526,13 +8536,13 @@ const selectLayoutRender = (state, prefs, rickRollCache) => {
const renderLayout = () => {
const renderedLayoutArray = [];
for (const row of layout.filter(r => r.components.length)) {
for (const row of layout.filter(r => r.components.filter(c => !filterArray.includes(c.type)).length)) {
let components = [];
renderedLayoutArray.push({ ...row,
components
});
for (const component of row.components.filter(c => !filterArray.includes(c.type))) {
for (const component of row.components) {
if (component.feed) {
const spocsConfig = component.spocs; // Are we still waiting on a feed/spocs, render what we have, and bail out early.
@ -11909,7 +11919,7 @@ class CachedIterable {
}
// CONCATENATED MODULE: ./node_modules/fluent/src/fallback.js
function _asyncIterator(iterable) { var method; if (typeof Symbol === "function") { if (Symbol.asyncIterator) { method = iterable[Symbol.asyncIterator]; if (method != null) return method.call(iterable); } if (Symbol.iterator) { method = iterable[Symbol.iterator]; if (method != null) return method.call(iterable); } } throw new TypeError("Object is not async iterable"); }
function _asyncIterator(iterable) { var method; if (typeof Symbol !== "undefined") { if (Symbol.asyncIterator) { method = iterable[Symbol.asyncIterator]; if (method != null) return method.call(iterable); } if (Symbol.iterator) { method = iterable[Symbol.iterator]; if (method != null) return method.call(iterable); } } throw new TypeError("Object is not async iterable"); }
/*
* @overview

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 12 KiB

Просмотреть файл

@ -1053,3 +1053,20 @@ This reports a failure in the Remote Settings loader to load messages for Activi
"value": "REMOTE_PROVIDER_ID"
}
```
## Trailhead experiment enrollment ping
This reports an enrollment ping when a user gets enrolled in a Trailhead experiment. Note that this ping is only collected through the Mozilla Events telemetry pipeline.
```js
{
"category": "activity_stream",
"method": "enroll",
"object": "preference_study"
"value": "activity-stream-firstup-trailhead-interrupts",
"extra_keys": {
"experimentType": "as-firstrun",
"branch": ["supercharge" | "join" | "sync" | "privacy" ...]
}
}
```

Просмотреть файл

@ -42,6 +42,7 @@ const TRAILHEAD_CONFIG = {
OVERRIDE_PREF: "trailhead.firstrun.branches",
DID_SEE_ABOUT_WELCOME_PREF: "trailhead.firstrun.didSeeAboutWelcome",
INTERRUPTS_EXPERIMENT_PREF: "trailhead.firstrun.interruptsExperiment",
TRIPLETS_ENROLLED_PREF: "trailhead.firstrun.tripletsEnrolled",
BRANCHES: {
interrupts: [
["control"],
@ -732,6 +733,14 @@ class _ASRouter {
return {experiment, interrupt, triplet};
}
// Dispatch a TRAILHEAD_ENROLL_EVENT action
_sendTrailheadEnrollEvent(data) {
this.dispatchToAS({
type: at.TRAILHEAD_ENROLL_EVENT,
data,
});
}
async setupTrailhead() {
// Don't initialize
if (this.state.trailheadInitialized || !Services.prefs.getBoolPref(TRAILHEAD_CONFIG.DID_SEE_ABOUT_WELCOME_PREF, false)) {
@ -742,18 +751,28 @@ class _ASRouter {
await this.setState({trailheadInitialized: true, trailheadInterrupt: interrupt, trailheadTriplet: triplet});
if (experiment) {
// In order for ping centre to pick this up, it MUST contain a substring activity-stream
const experimentName = `activity-stream-firstrun-trailhead-${experiment}`;
TelemetryEnvironment.setExperimentActive(
// In order for ping centre to pick this up, it MUST start with activity-stream
`activity-stream-firstrun-trailhead-${experiment}`,
experimentName,
experiment === "interrupts" ? interrupt : triplet,
{type: "as-firstrun"}
);
// On the first time setting the interrupts experiment, expose the branch
// for normandy to target for survey study.
// for normandy to target for survey study, and send out the enrollment ping.
if (experiment === "interrupts" &&
!Services.prefs.prefHasUserValue(TRAILHEAD_CONFIG.INTERRUPTS_EXPERIMENT_PREF)) {
Services.prefs.setStringPref(TRAILHEAD_CONFIG.INTERRUPTS_EXPERIMENT_PREF, interrupt);
this._sendTrailheadEnrollEvent({experiment: experimentName, type: "as-firstrun", branch: interrupt});
}
// On the first time setting the triplets experiment, send out the enrollment ping.
if (experiment === "triplets" &&
!Services.prefs.getBoolPref(TRAILHEAD_CONFIG.TRIPLETS_ENROLLED_PREF, false)) {
Services.prefs.setBoolPref(TRAILHEAD_CONFIG.TRIPLETS_ENROLLED_PREF, true);
this._sendTrailheadEnrollEvent({experiment: experimentName, type: "as-firstrun", branch: triplet});
}
}
}

Просмотреть файл

@ -343,7 +343,7 @@ const ONBOARDING_MESSAGES = async () => ([
label: {string_id: "onboarding-send-tabs-button"},
action: {
type: "OPEN_URL",
data: {args: "https://blog.mozilla.org/firefox/send-tabs-a-better-way/", where: "tabshifted"},
data: {args: "https://support.mozilla.org/kb/send-tab-firefox-desktop-mobile", where: "tabshifted"},
},
},
},

Просмотреть файл

@ -663,6 +663,14 @@ this.TelemetryFeed = class TelemetryFeed {
this.sendEvent(this.createUndesiredEvent(action));
}
handleTrailheadEnrollEvent(action) {
// Unlike `sendUTEvent`, we always send the event if AS's telemetry is enabled
// regardless of `this.eventTelemetryEnabled`.
if (this.telemetryEnabled) {
this.utEvents.sendTrailheadEnrollEvent(action.data);
}
}
async sendPageTakeoverData() {
if (this.telemetryEnabled) {
const value = {};
@ -764,6 +772,9 @@ this.TelemetryFeed = class TelemetryFeed {
case at.TELEMETRY_PERFORMANCE_EVENT:
this.sendEvent(this.createPerformanceEvent(action));
break;
case at.TRAILHEAD_ENROLL_EVENT:
this.handleTrailheadEnrollEvent(action);
break;
case at.UNINIT:
this.uninit();
break;

Просмотреть файл

@ -18,6 +18,7 @@ this.UTEventReporting = class UTEventReporting {
Services.telemetry.setEventRecordingEnabled("activity_stream", true);
this.sendUserEvent = this.sendUserEvent.bind(this);
this.sendSessionEndEvent = this.sendSessionEndEvent.bind(this);
this.sendTrailheadEnrollEvent = this.sendTrailheadEnrollEvent.bind(this);
}
_createExtras(data) {
@ -53,6 +54,19 @@ this.UTEventReporting = class UTEventReporting {
this._createExtras(data));
}
sendTrailheadEnrollEvent(data) {
Services.telemetry.recordEvent(
"activity_stream",
"enroll",
"preference_study",
data.experiment,
{
experimentType: data.type,
branch: data.branch,
}
);
}
uninit() {
Services.telemetry.setEventRecordingEnabled("activity_stream", false);
}

Просмотреть файл

@ -34,8 +34,8 @@ menu_action_open_new_window=פתיחה בחלון חדש
menu_action_open_private_window=פתיחה בלשונית פרטית חדשה
menu_action_dismiss=הסרה
menu_action_delete=מחיקה מההיסטוריה
menu_action_pin=הצמדה
menu_action_unpin=ביטול הצמדה
menu_action_pin=נעיצה
menu_action_unpin=ביטול נעיצה
confirm_history_delete_p1=למחוק כל עותק של העמוד הזה מההיסטוריה שלך?
# LOCALIZATION NOTE (confirm_history_delete_notice_p2): this string is displayed in
# the same dialog as confirm_history_delete_p1. "This action" refers to deleting a
@ -93,6 +93,7 @@ prefs_home_header=תוכן מסך הבית של Firefox
prefs_home_description=בחירת תוכן שיוצג במסך הבית של Firefox.
prefs_content_discovery_header=מסך הבית של Firefox
prefs_content_discovery_description=גילוי תוכן במסך הבית של Firefox מאפשר לך לגלות מאמרים רלוונטים ובאיכות גבוהה מכל רחבי הרשת.
prefs_content_discovery_button=השבתת גילוי תוכן
@ -151,6 +152,7 @@ pocket_read_even_more=צפייה בחדשות נוספות
pocket_more_reccommendations=המלצות נוספות
pocket_how_it_works=איך זה עובד
pocket_cta_button=קבלת Pocket
pocket_cta_text=שמירת הסיפורים שאהבת ב־Pocket על מנת למלא את מחשבתך בקריאה מרתקת.
highlights_empty_state=ניתן להתחיל בגלישה ואנו נציג בפניך מספר כתבות, סרטונים ועמודים שונים מעולים בהם ביקרת לאחרונה או שהוספת לסימניות.
# LOCALIZATION NOTE (topstories_empty_state): When there are no recommendations,

Просмотреть файл

@ -102,8 +102,8 @@ section_menu_action_move_down=Sposta giù
section_menu_action_privacy_notice=Informativa sulla privacy
firstrun_title=Porta Firefox con te
firstrun_content=Ritrova segnalibri, cronologia, password e altre impostazioni su tutti i tuoi dispositivi.
firstrun_learn_more_link=Scopri di più sullaccount Firefox
firstrun_form_header=Inserisci email
firstrun_learn_more_link=Ulteriori informazioni sullaccount Firefox
firstrun_form_header=Inserisci la tua email
firstrun_form_sub_header=per utilizzare Firefox Sync.
firstrun_email_input_placeholder=Email
firstrun_invalid_input=Inserire un indirizzo email valido

Просмотреть файл

@ -93,6 +93,7 @@ prefs_home_header=Firefox 首頁內容
prefs_home_description=選擇要在您的 Firefox 首頁顯示哪些內容。
prefs_content_discovery_header=Firefox 首頁
prefs_content_discovery_description=Firefox Home 的內容探索功能可隨您上網,為您尋找高品質而與您有關的文章。
prefs_content_discovery_button=關閉內容探索功能
@ -190,7 +191,7 @@ section_menu_action_privacy_notice=隱私權公告
# LOCALIZATION NOTE (firstrun_*). These strings are displayed only once, on the
# firstrun of the browser, they give an introduction to Firefox and Sync.
firstrun_title=Firefox 隨身帶著走
firstrun_content=在您的任何裝置上取得書籤、瀏覽紀錄、密碼及其他設定。
firstrun_content=在您的各種裝置上同步書籤、瀏覽紀錄、登入資訊及其他設定。
firstrun_learn_more_link=了解 Firefox Accounts 的更多資訊
# LOCALIZATION NOTE (firstrun_form_header and firstrun_form_sub_header):

Просмотреть файл

@ -17,8 +17,8 @@ window.gActivityStreamStrings = {
"menu_action_open_private_window": "פתיחה בלשונית פרטית חדשה",
"menu_action_dismiss": "הסרה",
"menu_action_delete": "מחיקה מההיסטוריה",
"menu_action_pin": "הצמדה",
"menu_action_unpin": "ביטול הצמדה",
"menu_action_pin": "נעיצה",
"menu_action_unpin": "ביטול נעיצה",
"confirm_history_delete_p1": "למחוק כל עותק של העמוד הזה מההיסטוריה שלך?",
"confirm_history_delete_notice_p2": "לא ניתן לבטל פעולה זו.",
"menu_action_save_to_pocket": "שמירה ל־Pocket",
@ -78,7 +78,7 @@ window.gActivityStreamStrings = {
"pocket_more_reccommendations": "המלצות נוספות",
"pocket_how_it_works": "איך זה עובד",
"pocket_cta_button": "קבלת Pocket",
"pocket_cta_text": "Save the stories you love in Pocket, and fuel your mind with fascinating reads.",
"pocket_cta_text": "שמירת הסיפורים שאהבת ב־Pocket על מנת למלא את מחשבתך בקריאה מרתקת.",
"highlights_empty_state": "ניתן להתחיל בגלישה ואנו נציג בפניך מספר כתבות, סרטונים ועמודים שונים מעולים בהם ביקרת לאחרונה או שהוספת לסימניות.",
"topstories_empty_state": "התעדכנת בכל הסיפורים. כדאי לנסות שוב מאוחר יותר כדי לקבל עוד סיפורים מובילים מאת {provider}. לא רוצה לחכות? ניתן לבחור נושא נפוץ כדי למצוא עוד סיפורים נפלאים מרחבי הרשת.",
"error_fallback_default_info": "אופס, משהו השתבש בעת טעינת התוכן הזה.",

Просмотреть файл

@ -95,8 +95,8 @@ window.gActivityStreamStrings = {
"section_menu_action_privacy_notice": "Informativa sulla privacy",
"firstrun_title": "Porta Firefox con te",
"firstrun_content": "Ritrova segnalibri, cronologia, password e altre impostazioni su tutti i tuoi dispositivi.",
"firstrun_learn_more_link": "Scopri di più sullaccount Firefox",
"firstrun_form_header": "Inserisci email",
"firstrun_learn_more_link": "Ulteriori informazioni sullaccount Firefox",
"firstrun_form_header": "Inserisci la tua email",
"firstrun_form_sub_header": "per utilizzare Firefox Sync.",
"firstrun_email_input_placeholder": "Email",
"firstrun_invalid_input": "Inserire un indirizzo email valido",

Просмотреть файл

@ -94,7 +94,7 @@ window.gActivityStreamStrings = {
"section_menu_action_move_down": "下移",
"section_menu_action_privacy_notice": "隱私權公告",
"firstrun_title": "Firefox 隨身帶著走",
"firstrun_content": "在您的任何裝置上取得書籤、瀏覽紀錄、密碼及其他設定。",
"firstrun_content": "在您的各種裝置上同步書籤、瀏覽紀錄、登入資訊及其他設定。",
"firstrun_learn_more_link": "了解 Firefox Accounts 的更多資訊",
"firstrun_form_header": "輸入您的電子郵件地址",
"firstrun_form_sub_header": "繼續前往 Firefox Sync",

Просмотреть файл

@ -247,6 +247,19 @@ export const UTSessionPing = Joi.array().items(
eventsTelemetryExtraKeys
);
export const trailheadEnrollExtraKeys = Joi.object().keys({
experimentType: Joi.string().required(),
branch: Joi.string().required(),
}).options({allowUnknown: false});
export const UTTrailheadEnrollPing = Joi.array().items(
Joi.string().required().valid("activity_stream"),
Joi.string().required().valid("enroll"),
Joi.string().required().valid("preference_study"),
Joi.string().required(),
trailheadEnrollExtraKeys
);
export function chaiAssertions(_chai, utils) {
const {Assertion} = _chai;

Просмотреть файл

@ -1601,13 +1601,18 @@ describe("ASRouter", () => {
describe(".setupTrailhead", () => {
let getBoolPrefStub;
let setStringPrefStub;
let setBoolPrefStub;
beforeEach(() => {
getBoolPrefStub = sandbox.stub(global.Services.prefs, "getBoolPref").withArgs(TRAILHEAD_CONFIG.DID_SEE_ABOUT_WELCOME_PREF).returns(true);
getBoolPrefStub = sandbox.stub(global.Services.prefs, "getBoolPref");
getBoolPrefStub.withArgs(TRAILHEAD_CONFIG.DID_SEE_ABOUT_WELCOME_PREF).returns(true);
getBoolPrefStub.withArgs(TRAILHEAD_CONFIG.TRIPLETS_ENROLLED_PREF).returns(false);
setStringPrefStub = sandbox.stub(global.Services.prefs, "setStringPref");
setBoolPrefStub = sandbox.stub(global.Services.prefs, "setBoolPref");
});
const configWithExperiment = {experiment: "interrupts", interrupt: "join", triplet: "privacy"};
const configWithInterruptsExperiment = {experiment: "interrupts", interrupt: "join", triplet: "privacy"};
const configWithTripletsExperiment = {experiment: "triplets", interrupt: "join", triplet: "privacy"};
const configWithoutExperiment = {experiment: "", interrupt: "control", triplet: ""};
it("should generates an experiment/branch configuration and update Router.state", async () => {
@ -1637,14 +1642,35 @@ describe("ASRouter", () => {
sandbox.spy(Router, "setState");
assert.notCalled(Router.setState);
});
it("should set active experiment if one is defined", async () => {
sandbox.stub(Router, "_generateTrailheadBranches").resolves(configWithExperiment);
it("should set active interrupts experiment if one is defined", async () => {
sandbox.stub(Router, "_generateTrailheadBranches").resolves(configWithInterruptsExperiment);
sandbox.stub(global.TelemetryEnvironment, "setExperimentActive");
sandbox.spy(Router, "_sendTrailheadEnrollEvent");
await Router.setupTrailhead();
assert.calledOnce(global.TelemetryEnvironment.setExperimentActive);
assert.calledWith(setStringPrefStub, TRAILHEAD_CONFIG.INTERRUPTS_EXPERIMENT_PREF, "join");
assert.calledWith(Router._sendTrailheadEnrollEvent, {
experiment: "activity-stream-firstrun-trailhead-interrupts",
type: "as-firstrun",
branch: "join",
});
});
it("should set active triplets experiment if one is defined", async () => {
sandbox.stub(Router, "_generateTrailheadBranches").resolves(configWithTripletsExperiment);
sandbox.stub(global.TelemetryEnvironment, "setExperimentActive");
sandbox.spy(Router, "_sendTrailheadEnrollEvent");
await Router.setupTrailhead();
assert.calledOnce(global.TelemetryEnvironment.setExperimentActive);
assert.calledWith(setBoolPrefStub, TRAILHEAD_CONFIG.TRIPLETS_ENROLLED_PREF, true);
assert.calledWith(Router._sendTrailheadEnrollEvent, {
experiment: "activity-stream-firstrun-trailhead-triplets",
type: "as-firstrun",
branch: "privacy",
});
});
it("should not set an active experiment if no experiment is defined", async () => {
sandbox.stub(Router, "_generateTrailheadBranches").resolves(configWithoutExperiment);

Просмотреть файл

@ -63,6 +63,11 @@ describe("<Trailhead>", () => {
assert.calledWith(dispatch, ac.UserEvent({event: at.SKIPPED_SIGNIN, value: {has_flow_params: false}}));
});
it("should NOT emit UserEvent SKIPPED_SIGNIN when closeModal is triggered by visibilitychange event", () => {
wrapper.instance().closeModal({type: "visibilitychange"});
assert.notCalled(dispatch);
});
it("should emit UserEvent SUBMIT_EMAIL when you submit the form", () => {
let form = wrapper.find("form");
assert.ok(form.exists());

Просмотреть файл

@ -353,4 +353,23 @@ describe("selectLayoutRender", () => {
assert.deepEqual(layoutRender[0].components[2].data.recommendations[0], {name: "rec", pos: 0});
});
it("should not render a row if no components exist after filter in that row", () => {
const fakeLayout = [{
width: 3,
components: [
{type: "TopSites"},
],
}, {
width: 3,
components: [
{type: "Message"},
],
}];
store.dispatch({type: at.DISCOVERY_STREAM_LAYOUT_UPDATE, data: {layout: fakeLayout}});
const {layoutRender} = selectLayoutRender(store.getState().DiscoveryStream, {"feeds.topsites": true}, []);
assert.equal(layoutRender[0].components[0].type, "TopSites");
assert.equal(layoutRender[1], undefined);
});
});

Просмотреть файл

@ -29,7 +29,12 @@ describe("TelemetryFeed", () => {
let fakeHomePage;
let fakeExtensionSettingsStore;
class PingCentre {sendPing() {} uninit() {} sendStructuredIngestionPing() {}}
class UTEventReporting {sendUserEvent() {} sendSessionEndEvent() {} uninit() {}}
class UTEventReporting {
sendUserEvent() {}
sendSessionEndEvent() {}
sendTrailheadEnrollEvent() {}
uninit() {}
}
class PerfService {
getMostRecentAbsMarkStartByName() { return 1234; }
mark() {}
@ -1132,6 +1137,15 @@ describe("TelemetryFeed", () => {
assert.calledWith(eventCreator, action.data);
assert.calledWith(sendEvent, eventCreator.returnValue);
});
it("should call .handleTrailheadEnrollEvent on a TRAILHEAD_ENROLL_EVENT action", () => {
const data = {experiment: "foo", type: "bar", branch: "baz"};
const action = {type: at.TRAILHEAD_ENROLL_EVENT, data};
sandbox.spy(instance, "handleTrailheadEnrollEvent");
instance.onAction(action);
assert.calledWith(instance.handleTrailheadEnrollEvent, action);
});
});
describe("#handlePagePrerendered", () => {
it("should not throw if there is no session for the given port ID", () => {
@ -1363,4 +1377,26 @@ describe("TelemetryFeed", () => {
assert.equal(url, `${fakeEndpoint}/testPingType/1/${fakeUUIDWithoutBraces}`);
});
});
describe("#handleTrailheadEnrollEvent", () => {
it("should send a TRAILHEAD_ENROLL_EVENT if the telemetry is enabled", () => {
FakePrefs.prototype.prefs[TELEMETRY_PREF] = true;
const data = {experiment: "foo", type: "bar", branch: "baz"};
instance = new TelemetryFeed();
sandbox.stub(instance.utEvents, "sendTrailheadEnrollEvent");
instance.handleTrailheadEnrollEvent({data});
assert.calledWith(instance.utEvents.sendTrailheadEnrollEvent, data);
});
it("should not send TRAILHEAD_ENROLL_EVENT if the telemetry is disabled", () => {
FakePrefs.prototype.prefs[TELEMETRY_PREF] = false;
const data = {experiment: "foo", type: "bar", branch: "baz"};
instance = new TelemetryFeed();
sandbox.stub(instance.utEvents, "sendTrailheadEnrollEvent");
instance.handleTrailheadEnrollEvent({data});
assert.notCalled(instance.utEvents.sendTrailheadEnrollEvent);
});
});
});

Просмотреть файл

@ -1,5 +1,6 @@
import {
UTSessionPing,
UTTrailheadEnrollPing,
UTUserEventPing,
} from "test/schemas/pings";
import {GlobalOverrider} from "test/unit/utils";
@ -40,6 +41,17 @@ const FAKE_SESSION_PING_UT = [
"page": "about:newtab",
},
];
const FAKE_TRAILHEAD_ENROLL_EVENT = {
experiment: "activity-stream-trailhead-firstrun-interrupts",
type: "as-firstrun",
branch: "supercharge",
};
const FAKE_TRAILHEAD_ENROLL_EVENT_UT = [
"activity_stream", "enroll", "preference_study", "activity-stream-trailhead-firstrun-interrupts", {
experimentType: "as-firstrun",
branch: "supercharge",
},
];
describe("UTEventReporting", () => {
let globals;
@ -79,6 +91,16 @@ describe("UTEventReporting", () => {
});
});
describe("#sendTrailheadEnrollEvent()", () => {
it("should queue up the correct data to send to Events Telemetry", async () => {
utEvents.sendTrailheadEnrollEvent(FAKE_TRAILHEAD_ENROLL_EVENT);
assert.calledWithExactly(global.Services.telemetry.recordEvent, ...FAKE_TRAILHEAD_ENROLL_EVENT_UT);
let ping = global.Services.telemetry.recordEvent.firstCall.args;
assert.validate(ping, UTTrailheadEnrollPing);
});
});
describe("#uninit()", () => {
it("should call setEventRecordingEnabled with a false value", () => {
assert.equal(global.Services.telemetry.setEventRecordingEnabled.firstCall.args[0], "activity_stream");