refactor(email-opt-in): Extract the email-opt-in frontend logic for re-use. (#5275) r=@vbudhram
Extract the email-opt-in login to a mixin for use in the email-first flow.
This commit is contained in:
Родитель
59f014ed01
Коммит
8fafad7f41
|
@ -0,0 +1,43 @@
|
|||
/* 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/. */
|
||||
|
||||
/**
|
||||
* Mixin that provides email opt-in functionality.
|
||||
*
|
||||
* Sets `isEmailOptInVisible` in the context.
|
||||
* Provides `hasOptedInToEmail` to query whether the user has
|
||||
* opted-in.
|
||||
*/
|
||||
define(function (require, exports, module) {
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
initialize (options = {}) {
|
||||
this._experimentGroupingRules = options.experimentGroupingRules;
|
||||
},
|
||||
|
||||
setInitialContext (context) {
|
||||
context.set('isEmailOptInVisible', this._isEmailOptInEnabled());
|
||||
},
|
||||
|
||||
afterRender () {
|
||||
this.logViewEvent(`email-optin.visible.${String(this._isEmailOptInEnabled())}`);
|
||||
},
|
||||
|
||||
_isEmailOptInEnabled () {
|
||||
return !! this._experimentGroupingRules.choose('communicationPrefsVisible', {
|
||||
lang: this.navigator.language
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Query whether user has opted-in to marketing email.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
hasOptedInToMarketingEmail () {
|
||||
return !! this.$('.marketing-email-optin').is(':checked');
|
||||
}
|
||||
};
|
||||
});
|
|
@ -10,6 +10,7 @@ define(function (require, exports, module) {
|
|||
const CheckboxMixin = require('views/mixins/checkbox-mixin');
|
||||
const Cocktail = require('cocktail');
|
||||
const CoppaAgeInput = require('views/coppa/coppa-age-input');
|
||||
const EmailOptInMixin = require('views/mixins/email-opt-in-mixin');
|
||||
const ExperimentMixin = require('views/mixins/experiment-mixin');
|
||||
const FlowBeginMixin = require('views/mixins/flow-begin-mixin');
|
||||
const FormPrefillMixin = require('views/mixins/form-prefill-mixin');
|
||||
|
@ -91,9 +92,6 @@ define(function (require, exports, module) {
|
|||
},
|
||||
|
||||
afterRender () {
|
||||
this.logViewEvent('email-optin.visible.' +
|
||||
String(this._isEmailOptInEnabled()));
|
||||
|
||||
return this._createCoppaView()
|
||||
.then(() => FormView.prototype.afterRender.call(this));
|
||||
},
|
||||
|
@ -150,7 +148,6 @@ define(function (require, exports, module) {
|
|||
forceEmail: forceEmail,
|
||||
isAmoMigration: this.isAmoMigration(),
|
||||
isCustomizeSyncChecked: relier.isCustomizeSyncChecked(),
|
||||
isEmailOptInVisible: this._isEmailOptInEnabled(),
|
||||
isSignInEnabled: ! forceEmail,
|
||||
isSync: isSync,
|
||||
isSyncMigration: this.isSyncMigration(),
|
||||
|
@ -334,7 +331,7 @@ define(function (require, exports, module) {
|
|||
var account = this.user.initAccount({
|
||||
customizeSync: this.$('.customize-sync').is(':checked'),
|
||||
email: this.getElementValue('.email'),
|
||||
needsOptedInToMarketingEmail: this.$('.marketing-email-optin').is(':checked')
|
||||
needsOptedInToMarketingEmail: this.hasOptedInToMarketingEmail()
|
||||
});
|
||||
|
||||
if (this.relier.isSync()) {
|
||||
|
@ -348,12 +345,6 @@ define(function (require, exports, module) {
|
|||
_suggestSignIn (err) {
|
||||
err.forceMessage = t('Account already exists. <a href="/signin">Sign in</a>');
|
||||
return this.unsafeDisplayError(err);
|
||||
},
|
||||
|
||||
_isEmailOptInEnabled () {
|
||||
return !! this._experimentGroupingRules.choose('communicationPrefsVisible', {
|
||||
lang: this.navigator.language
|
||||
});
|
||||
}
|
||||
}, {
|
||||
ENTRYPOINT: 'fxa:signup'
|
||||
|
@ -363,6 +354,7 @@ define(function (require, exports, module) {
|
|||
View,
|
||||
AccountResetMixin,
|
||||
CheckboxMixin,
|
||||
EmailOptInMixin,
|
||||
ExperimentMixin,
|
||||
FlowBeginMixin,
|
||||
FormPrefillMixin,
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/* 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/. */
|
||||
|
||||
define(function (require, exports, module) {
|
||||
'use strict';
|
||||
|
||||
const { assert } = require('chai');
|
||||
const Cocktail = require('cocktail');
|
||||
const EmailOptInMixin = require('views/mixins/email-opt-in-mixin');
|
||||
const sinon = require('sinon');
|
||||
const BaseView = require('views/base');
|
||||
|
||||
const View = BaseView.extend({
|
||||
template: () => `
|
||||
<input type="checkbox" class="marketing-email-optin" checked>Opt-in to email</input>
|
||||
`
|
||||
});
|
||||
|
||||
Cocktail.mixin(
|
||||
View,
|
||||
EmailOptInMixin
|
||||
);
|
||||
|
||||
describe('views/mixins/email-opt-in-mixin', function () {
|
||||
let experimentGroupingRules;
|
||||
let view;
|
||||
|
||||
beforeEach(() => {
|
||||
experimentGroupingRules = {
|
||||
choose: () => {}
|
||||
};
|
||||
|
||||
view = new View({
|
||||
experimentGroupingRules
|
||||
});
|
||||
});
|
||||
|
||||
it('exports correct interface', function () {
|
||||
assert.isObject(EmailOptInMixin);
|
||||
assert.lengthOf(Object.keys(EmailOptInMixin), 5);
|
||||
assert.isFunction(EmailOptInMixin.hasOptedInToMarketingEmail);
|
||||
});
|
||||
|
||||
describe('render', () => {
|
||||
let communicationPrefsVisible;
|
||||
|
||||
beforeEach(() => {
|
||||
sinon.stub(experimentGroupingRules, 'choose', () => communicationPrefsVisible);
|
||||
sinon.spy(view, 'logViewEvent');
|
||||
sinon.spy(view, 'template');
|
||||
});
|
||||
|
||||
|
||||
describe('enabled for user', () => {
|
||||
beforeEach(() => {
|
||||
communicationPrefsVisible = true;
|
||||
return view.render();
|
||||
});
|
||||
|
||||
it('sets `isEmailOptInVisible=true, logs correctly`', () => {
|
||||
assert.isTrue(view.template.calledOnce);
|
||||
const templateArgs = view.template.args[0][0];
|
||||
assert.isTrue(templateArgs.isEmailOptInVisible);
|
||||
|
||||
assert.isTrue(view.logViewEvent.calledOnce);
|
||||
assert.isTrue(view.logViewEvent.calledWith('email-optin.visible.true'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('disabled for user', () => {
|
||||
beforeEach(() => {
|
||||
communicationPrefsVisible = false;
|
||||
return view.render();
|
||||
});
|
||||
|
||||
it('sets `isEmailOptInVisible=false, logs correctly`', () => {
|
||||
assert.isTrue(view.template.calledOnce);
|
||||
const templateArgs = view.template.args[0][0];
|
||||
assert.isFalse(templateArgs.isEmailOptInVisible);
|
||||
|
||||
assert.isTrue(view.logViewEvent.calledOnce);
|
||||
assert.isTrue(view.logViewEvent.calledWith('email-optin.visible.false'));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasOptedInToMarketingEmail', () => {
|
||||
beforeEach(() => {
|
||||
return view.render();
|
||||
});
|
||||
|
||||
it('returns `true` if the checkbox is checked', () => {
|
||||
view.$('.marketing-email-optin').attr('checked', 'checked');
|
||||
assert.isTrue(view.hasOptedInToMarketingEmail());
|
||||
});
|
||||
|
||||
it('returns `false` if the checkbox is unchecked', () => {
|
||||
view.$('.marketing-email-optin').removeAttr('checked');
|
||||
assert.isFalse(view.hasOptedInToMarketingEmail());
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -850,26 +850,25 @@ define(function (require, exports, module) {
|
|||
|
||||
describe('signup succeeds', function () {
|
||||
beforeEach(function () {
|
||||
sinon.stub(view, 'signUp', function () {
|
||||
return p();
|
||||
});
|
||||
sinon.stub(view, 'signUp', () => p());
|
||||
sinon.stub(view, 'hasOptedInToMarketingEmail', () => true);
|
||||
|
||||
return view.submit();
|
||||
});
|
||||
|
||||
it('does not call view.signIn', function () {
|
||||
it('calls view.signUp correctly, does not display any errors', function () {
|
||||
assert.isFalse(view.signIn.called);
|
||||
});
|
||||
|
||||
it('calls view.signUp correctly', function () {
|
||||
assert.equal(view.signUp.callCount, 1);
|
||||
|
||||
var args = view.signUp.args[0];
|
||||
assert.instanceOf(args[0], Account);
|
||||
assert.equal(args[1], 'password');
|
||||
});
|
||||
const account = args[0];
|
||||
assert.instanceOf(account, Account);
|
||||
assert.equal(account.get('email'), email);
|
||||
assert.isTrue(account.get('needsOptedInToMarketingEmail'));
|
||||
assert.isFalse(account.get('customizeSync'));
|
||||
|
||||
assert.equal(args[1], 'password');
|
||||
|
||||
it('does not display any errors', function () {
|
||||
assert.isFalse(view.displayError.called);
|
||||
assert.isFalse(view.unsafeDisplayError.called);
|
||||
});
|
||||
|
|
|
@ -145,6 +145,7 @@ function (Translator, Session) {
|
|||
'../tests/spec/views/mixins/back-mixin',
|
||||
'../tests/spec/views/mixins/checkbox-mixin',
|
||||
'../tests/spec/views/mixins/connect-another-device-mixin',
|
||||
'../tests/spec/views/mixins/email-opt-in-mixin',
|
||||
'../tests/spec/views/mixins/experiment-mixin',
|
||||
'../tests/spec/views/mixins/external-links-mixin',
|
||||
'../tests/spec/views/mixins/floating-placeholder-mixin',
|
||||
|
|
Загрузка…
Ссылка в новой задаче