зеркало из https://github.com/mozilla/fxa.git
Merge pull request #16169 from mozilla/FXA-8759
feat(content): Remove experiment logic around third party auth
This commit is contained in:
Коммит
f793fba3f1
|
@ -23,11 +23,7 @@ test.describe('severity-1 #smoke', () => {
|
|||
'Please contact FxA admin to get credentials for Google account'
|
||||
);
|
||||
test.slow();
|
||||
await page.goto(
|
||||
target.contentServerUrl +
|
||||
'?forceExperiment=thirdPartyAuth&forceExperimentGroup=treatment',
|
||||
{ waitUntil: 'load' }
|
||||
);
|
||||
await page.goto(target.contentServerUrl, { waitUntil: 'load' });
|
||||
|
||||
await login.clickContinueWithGoogle();
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ const experimentGroupingRules = [
|
|||
require('./is-sampled-user'),
|
||||
require('./sentry'),
|
||||
require('./push'),
|
||||
require('./third-party-auth'),
|
||||
require('./generalized-react-app'),
|
||||
].map((ExperimentGroupingRule) => new ExperimentGroupingRule());
|
||||
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const BaseGroupingRule = require('./base');
|
||||
const GROUPS = [
|
||||
// Treatment branches
|
||||
'treatment',
|
||||
];
|
||||
|
||||
// This experiment is disabled by default. If you would like to go through
|
||||
// the flow, load email-first screen and append query params
|
||||
// `?forceExperiment=thirdPartyAuth&forceExperimentGroup=treatment`
|
||||
const ROLLOUT_RATE = 1.0;
|
||||
|
||||
module.exports = class ThirdPartyAuth extends BaseGroupingRule {
|
||||
constructor() {
|
||||
super();
|
||||
this.name = 'thirdPartyAuth';
|
||||
|
||||
// Easier to set class properties for testability
|
||||
this.groups = GROUPS;
|
||||
this.rolloutRate = ROLLOUT_RATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* For this experiment, we are doing a staged rollout.
|
||||
*
|
||||
* @param {Object} subject data used to decide
|
||||
* @param {String} clientId clientId
|
||||
* @returns {Any}
|
||||
*/
|
||||
choose(subject = {}) {
|
||||
let choice = false;
|
||||
const { relier } = subject;
|
||||
|
||||
if (!relier) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (relier.isSync()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.bernoulliTrial(this.rolloutRate, subject.uniqueUserId)) {
|
||||
choice = this.uniformChoice(GROUPS, subject.uniqueUserId);
|
||||
}
|
||||
|
||||
return choice;
|
||||
}
|
||||
};
|
|
@ -43,21 +43,9 @@
|
|||
</div>
|
||||
</form>
|
||||
|
||||
{{#isInThirdPartyAuthExperiment}}
|
||||
{{^isSync}}
|
||||
{{{ unsafeThirdPartyAuthHTML }}}
|
||||
{{/isSync}}
|
||||
{{/isInThirdPartyAuthExperiment}}
|
||||
|
||||
{{^isInThirdPartyAuthExperiment}}
|
||||
{{^isSync}}
|
||||
<div class="text-xs text-grey-500 mb-0 mt-5">
|
||||
<p id="firefox-family-services">
|
||||
{{#t}}A Mozilla account also unlocks access to more privacy-protecting products from Mozilla.{{/t}}
|
||||
</p>
|
||||
</div>
|
||||
{{/isSync}}
|
||||
{{/isInThirdPartyAuthExperiment}}
|
||||
{{^isSync}}
|
||||
{{{ unsafeThirdPartyAuthHTML }}}
|
||||
{{/isSync}}
|
||||
|
||||
<div class="text-xs text-grey-500 mb-0 mt-5">
|
||||
{{#isSync}}
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
import ExperimentMixin from './experiment-mixin';
|
||||
const EXPERIMENT_NAME = 'thirdPartyAuth';
|
||||
|
||||
export default {
|
||||
dependsOn: [ExperimentMixin],
|
||||
|
||||
isInThirdPartyAuthExperiment() {
|
||||
const experimentGroup = this.getAndReportExperimentGroup(EXPERIMENT_NAME, {
|
||||
relier: this.relier,
|
||||
});
|
||||
|
||||
return experimentGroup === 'treatment';
|
||||
},
|
||||
};
|
|
@ -5,13 +5,12 @@
|
|||
import SigninMixin from './signin-mixin';
|
||||
import Storage from '../../lib/storage';
|
||||
import Url from '../../lib/url';
|
||||
import ThirdPartyAuthExperimentMixin from '../../views/mixins/third-party-auth-experiment-mixin';
|
||||
import FlowEventsMixin from '../mixins/flow-events-mixin';
|
||||
|
||||
const DEFAULT_SCOPES = 'openid email profile';
|
||||
|
||||
export default {
|
||||
dependsOn: [SigninMixin, ThirdPartyAuthExperimentMixin, FlowEventsMixin],
|
||||
dependsOn: [SigninMixin, FlowEventsMixin],
|
||||
|
||||
events: {
|
||||
'click #google-login-button': 'googleSignIn',
|
||||
|
@ -24,12 +23,6 @@ export default {
|
|||
this.initializeFlowEvents();
|
||||
},
|
||||
|
||||
setInitialContext(context) {
|
||||
context.set({
|
||||
isInThirdPartyAuthExperiment: this.isInThirdPartyAuthExperiment(),
|
||||
});
|
||||
},
|
||||
|
||||
beforeRender() {
|
||||
// Check to see if this is a request to deeplink into Google/Apple login
|
||||
// flow. A bit of a hack but we do a promise to keep our loading indicator on while
|
||||
|
@ -53,17 +46,17 @@ export default {
|
|||
const thirdPartyAuth = Storage.factory('localStorage', this.window).get(
|
||||
'fxa_third_party_params'
|
||||
);
|
||||
|
||||
|
||||
// Since this mixin is loaded from multiple views it is possible to have
|
||||
// a race condition and call complete multiple times. We only want to call it
|
||||
// on the `enter-email` view.
|
||||
if (thirdPartyAuth && this.viewName ==='enter-email') {
|
||||
if (thirdPartyAuth && this.viewName === 'enter-email') {
|
||||
return this.completeSignIn();
|
||||
}
|
||||
|
||||
if (this.isInThirdPartyAuthExperiment()) {
|
||||
this.logViewEvent('thirdPartyAuth');
|
||||
}
|
||||
// TODO: determine if we want to log this event for all views,
|
||||
// or not at all since this component is no longer behind an experiment flag
|
||||
this.logViewEvent('thirdPartyAuth');
|
||||
},
|
||||
|
||||
clearStoredParams() {
|
||||
|
@ -107,7 +100,7 @@ export default {
|
|||
prompt: 'consent',
|
||||
response_type: 'code',
|
||||
disallow_webview: true,
|
||||
ack_webview_shutdown:'2024-09-30'
|
||||
ack_webview_shutdown: '2024-09-30',
|
||||
};
|
||||
/* eslint-enable camelcase */
|
||||
for (const p in params) {
|
||||
|
@ -154,7 +147,7 @@ export default {
|
|||
access_type: 'offline',
|
||||
prompt: 'consent',
|
||||
response_type: 'code id_token',
|
||||
response_mode: 'form_post'
|
||||
response_mode: 'form_post',
|
||||
};
|
||||
/* eslint-enable camelcase */
|
||||
for (const p in params) {
|
||||
|
@ -201,7 +194,7 @@ export default {
|
|||
);
|
||||
const code = authParams.code;
|
||||
const provider = authParams.provider || 'google';
|
||||
|
||||
|
||||
return this.user
|
||||
.verifyAccountThirdParty(account, this.relier, code, provider)
|
||||
.then((updatedAccount) => {
|
||||
|
@ -210,12 +203,14 @@ export default {
|
|||
this.logFlowEvent(`${provider}.signin-complete`);
|
||||
|
||||
this.metrics.flush();
|
||||
|
||||
|
||||
// Sync service requires a password to be set before it can be used.
|
||||
// Note that once a password is set, the user will not have an option to use
|
||||
// third party login for Sync since it always requires a password.
|
||||
if (this.relier.isSync()) {
|
||||
return this.navigate('/post_verify/third_party_auth/set_password', { provider });
|
||||
return this.navigate('/post_verify/third_party_auth/set_password', {
|
||||
provider,
|
||||
});
|
||||
}
|
||||
|
||||
return this.signIn(updatedAccount);
|
||||
|
|
|
@ -9,7 +9,7 @@ import sinon from 'sinon';
|
|||
|
||||
describe('lib/experiments/grouping-rules/index', () => {
|
||||
it('EXPERIMENT_NAMES is exported', () => {
|
||||
assert.lengthOf(ExperimentGroupingRules.EXPERIMENT_NAMES, 6);
|
||||
assert.lengthOf(ExperimentGroupingRules.EXPERIMENT_NAMES, 5);
|
||||
});
|
||||
|
||||
describe('choose', () => {
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
import { assert } from 'chai';
|
||||
import Experiment from 'lib/experiments/grouping-rules/third-party-auth';
|
||||
|
||||
describe('lib/experiments/grouping-rules/third-party-auth', () => {
|
||||
let experiment;
|
||||
|
||||
beforeEach(() => {
|
||||
experiment = new Experiment();
|
||||
});
|
||||
|
||||
describe('choose', () => {
|
||||
it('returns false if no relier', () => {
|
||||
assert.isFalse(
|
||||
experiment.choose({
|
||||
experimentGroupingRules: { choose: () => experiment.name },
|
||||
uniqueUserId: 'user-id',
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('returns false if sync service', () => {
|
||||
assert.isFalse(
|
||||
experiment.choose({
|
||||
experimentGroupingRules: { choose: () => experiment.name },
|
||||
relier: { isSync: () => true },
|
||||
uniqueUserId: 'user-id',
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('returns treatment if valid', () => {
|
||||
const rules = experiment.groups;
|
||||
assert.isTrue(
|
||||
rules.include(
|
||||
experiment.choose({
|
||||
experimentGroupingRules: { choose: () => experiment.name },
|
||||
relier: { isSync: () => false },
|
||||
uniqueUserId: 'user-id',
|
||||
})
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('returns false if rollout 0%', () => {
|
||||
experiment.rolloutRate = 0;
|
||||
assert.isFalse(
|
||||
experiment.choose({
|
||||
experimentGroupingRules: { choose: () => experiment.name },
|
||||
relier: { isSync: () => true },
|
||||
uniqueUserId: 'user-id',
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -88,15 +88,6 @@ describe('views/index', () => {
|
|||
sinon.spy(view, 'replaceCurrentPage');
|
||||
});
|
||||
|
||||
it('renders the firefox-family services copy', () => {
|
||||
return view.render().then(() => {
|
||||
assert.include(
|
||||
view.$(Selectors.FIREFOX_FAMILY_SERVICES).text(),
|
||||
'A Mozilla account also unlocks access to more privacy-protecting products from Mozilla.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('prefills the email with React prefillEmail=email and does not navigate', () => {
|
||||
const prefillEmail = 'mycoolemail@gmail.com';
|
||||
relier.set('prefillEmail', prefillEmail);
|
||||
|
@ -156,7 +147,7 @@ describe('views/index', () => {
|
|||
});
|
||||
|
||||
describe('current account', () => {
|
||||
it('replaces current page with to `/settings`', () => {
|
||||
it('replaces current page with `/settings`', () => {
|
||||
const signedInAccount = user.initAccount({
|
||||
sessionToken: 'token',
|
||||
});
|
||||
|
@ -237,33 +228,51 @@ describe('views/index', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('user is in thirdPartyAuth experiment', () => {
|
||||
beforeEach(() => {
|
||||
sinon
|
||||
.stub(view, 'isInThirdPartyAuthExperiment')
|
||||
.callsFake(() => true);
|
||||
it('renders third party auth options when not sync', () => {
|
||||
return view.render().then(() => {
|
||||
assert.lengthOf(view.$(Selectors.FIREFOX_FAMILY_SERVICES), 0);
|
||||
assert.lengthOf(view.$(Selectors.THIRD_PARTY_AUTH.GOOGLE), 1);
|
||||
assert.lengthOf(view.$(Selectors.THIRD_PARTY_AUTH.APPLE), 1);
|
||||
});
|
||||
});
|
||||
|
||||
it('renders as expected when not sync', () => {
|
||||
return view.render().then(() => {
|
||||
assert.lengthOf(view.$(Selectors.FIREFOX_FAMILY_SERVICES), 0);
|
||||
assert.lengthOf(view.$(Selectors.THIRD_PARTY_AUTH.GOOGLE), 1);
|
||||
assert.lengthOf(view.$(Selectors.THIRD_PARTY_AUTH.APPLE), 1);
|
||||
});
|
||||
it('does not render the firefox-family services copy when not sync', () => {
|
||||
return view.render().then(() => {
|
||||
assert.notInclude(
|
||||
view.$(Selectors.FIREFOX_FAMILY_SERVICES).text(),
|
||||
'A Mozilla account also unlocks access to more privacy-protecting products from Mozilla.'
|
||||
);
|
||||
});
|
||||
it('renders as expected when sync', () => {
|
||||
relier.set({
|
||||
action: 'email',
|
||||
service: 'sync',
|
||||
serviceName: 'Firefox Sync',
|
||||
});
|
||||
sinon.stub(relier, 'isSync').callsFake(() => true);
|
||||
});
|
||||
|
||||
return view.render().then(() => {
|
||||
assert.lengthOf(view.$(Selectors.FIREFOX_FAMILY_SERVICES), 1);
|
||||
assert.lengthOf(view.$(Selectors.THIRD_PARTY_AUTH.GOOGLE), 0);
|
||||
assert.lengthOf(view.$(Selectors.THIRD_PARTY_AUTH.APPLE), 0);
|
||||
});
|
||||
it('does not render third party auth options when sync', () => {
|
||||
relier.set({
|
||||
action: 'email',
|
||||
service: 'sync',
|
||||
serviceName: 'Firefox Sync',
|
||||
});
|
||||
sinon.stub(relier, 'isSync').callsFake(() => true);
|
||||
|
||||
return view.render().then(() => {
|
||||
assert.lengthOf(view.$(Selectors.FIREFOX_FAMILY_SERVICES), 1);
|
||||
assert.lengthOf(view.$(Selectors.THIRD_PARTY_AUTH.GOOGLE), 0);
|
||||
assert.lengthOf(view.$(Selectors.THIRD_PARTY_AUTH.APPLE), 0);
|
||||
});
|
||||
});
|
||||
|
||||
it('renders the firefox-family services copy when sync', () => {
|
||||
relier.set({
|
||||
action: 'email',
|
||||
service: 'sync',
|
||||
serviceName: 'Firefox Sync',
|
||||
});
|
||||
sinon.stub(relier, 'isSync').callsFake(() => true);
|
||||
|
||||
return view.render().then(() => {
|
||||
assert.include(
|
||||
view.$(Selectors.FIREFOX_FAMILY_SERVICES).text(),
|
||||
'A Mozilla account also unlocks access to more privacy-protecting products from Mozilla.'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -521,7 +530,6 @@ describe('views/index', () => {
|
|||
assert.lengthOf(view.$(Selectors.EMAIL), 1);
|
||||
assert.include(view.$(Selectors.SUB_HEADER).text(), expectedServiceName);
|
||||
assert.isTrue(view.chooseEmailActionPage.calledOnce);
|
||||
assert.lengthOf(view.$(Selectors.FIREFOX_FAMILY_SERVICES), 1);
|
||||
|
||||
assert.isTrue(view.logFlowEventOnce.calledOnceWith('begin'));
|
||||
});
|
||||
|
|
|
@ -78,7 +78,6 @@ describe('views/mixins/third-party-auth-mixin', function () {
|
|||
user,
|
||||
});
|
||||
sinon.spy(notifier, 'trigger');
|
||||
sinon.stub(view, 'isInThirdPartyAuthExperiment').callsFake(() => true);
|
||||
await view.render();
|
||||
});
|
||||
|
||||
|
|
|
@ -16,14 +16,6 @@ export default {
|
|||
} as Meta;
|
||||
|
||||
export const Default = () => {
|
||||
return (
|
||||
<AppLayout>
|
||||
<Subject enabled showSeparator />
|
||||
</AppLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export const Disabled = () => {
|
||||
return (
|
||||
<AppLayout>
|
||||
<Subject showSeparator />
|
||||
|
@ -34,7 +26,7 @@ export const Disabled = () => {
|
|||
export const NoSeparator = () => {
|
||||
return (
|
||||
<AppLayout>
|
||||
<Subject enabled showSeparator={false} />
|
||||
<Subject showSeparator={false} />
|
||||
</AppLayout>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -14,7 +14,6 @@ import { AUTH_PROVIDER } from 'fxa-auth-client/browser';
|
|||
import { ReactElement } from 'react-markdown/lib/react-markdown';
|
||||
|
||||
export type ThirdPartyAuthProps = {
|
||||
enabled?: boolean;
|
||||
onContinueWithGoogle?: FormEventHandler<HTMLFormElement>;
|
||||
onContinueWithApple?: FormEventHandler<HTMLFormElement>;
|
||||
showSeparator?: boolean;
|
||||
|
@ -26,7 +25,6 @@ export type ThirdPartyAuthProps = {
|
|||
* It handles user sign-in with the respective provider when the buttons are clicked.
|
||||
*/
|
||||
const ThirdPartyAuth = ({
|
||||
enabled = false,
|
||||
onContinueWithGoogle,
|
||||
onContinueWithApple,
|
||||
showSeparator = true,
|
||||
|
@ -44,10 +42,6 @@ const ThirdPartyAuth = ({
|
|||
}
|
||||
});
|
||||
|
||||
if (!enabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
async function completeSignIn() {
|
||||
try {
|
||||
const authParams = Storage.factory('localStorage', window).get(
|
||||
|
|
|
@ -167,9 +167,7 @@ const Signin = ({
|
|||
</div>
|
||||
</form>
|
||||
|
||||
{/* TODO: We will need to pull the enabled flag from feature flags or experiment data
|
||||
*/}
|
||||
<ThirdPartyAuth {...{ enabled: false }} />
|
||||
<ThirdPartyAuth />
|
||||
|
||||
<TermsPrivacyAgreement {...{ isPocketClient, isMonitorClient }} />
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче