Skip to content

Commit

Permalink
Merge pull request #15218 from mozilla/FXA-7312
Browse files Browse the repository at this point in the history
feat(react): Add logic for and effectively turn simpleRoutes to 100% rollout in prod
  • Loading branch information
LZoog authored Apr 26, 2023
2 parents d35606a + a66dae3 commit 8fbea9c
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 30 deletions.
3 changes: 2 additions & 1 deletion packages/functional-tests/tests/signUp/signUp.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ test.describe('signup here', () => {

// Verify navigated to the cannot create account page
await page.waitForURL(/cannot_create_account/);
expect(await login.cannotCreateAccountHeader()).toBe(true);
// TODO: this is flaky
// expect(await login.cannotCreateAccountHeader()).toBe(true);
});

test('sign up with non matching passwords', async ({
Expand Down
30 changes: 24 additions & 6 deletions packages/fxa-content-server/app/scripts/lib/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ import { getClientReactRouteGroups } from '../../../server/lib/routes/react-app/

const NAVIGATE_AWAY_IN_MOBILE_DELAY_MS = 75;

// React route groups specified here will effectively be set to
// 100% roll out in production. Only add group names here once they've
// been verified in production at the 15% experiment roll out.
const ALWAYS_SHOWN_REACT_GROUPS = ['simpleRoutes'];

function getView(ViewOrPath) {
if (typeof ViewOrPath === 'string') {
return import(`../views/${ViewOrPath}`).then((result) => {
Expand Down Expand Up @@ -447,7 +452,21 @@ Router = Router.extend({
(route) => routeName === route
)
) {
return this.reactRouteGroups[routeGroup].featureFlagOn;
// Relier OAuth check is temporary until we work on OAuth flows; at the time of writing
// we don't want to show the React version of reset password for example if users are
// trying to reset through a relying party, e.g. going to Firefox Monitor > sign in >
// reset PW, since there is a lot of logic we must port over for that to function
// correctly. However, the relier for simple routes doesn't matter since the simple
// routes don't contain any oauth logic.
if (routeGroup !== 'simpleRoutes' && this.relier.isOAuth()) {
return false;
}

return (
this.reactRouteGroups[routeGroup].featureFlagOn &&
(this.isInReactExperiment() ||
ALWAYS_SHOWN_REACT_GROUPS.includes(routeGroup))
);
}
}
return false;
Expand All @@ -461,11 +480,7 @@ Router = Router.extend({
) {
const showReactApp = this.showReactApp(routeName);

// Relier OAuth check is temporary until we work on OAuth flows; at the time of writing we
// don't want to show the React version of reset password if users are trying to reset
// through a relying party, e.g. going to Firefox Monitor > sign in > reset PW, since there
// is a lot of logic we must port over for that to function correctly.
if (!this.relier.isOAuth() && showReactApp && this.isInReactExperiment()) {
if (showReactApp) {
const { deviceId, flowBeginTime, flowId } =
this.metrics.getFlowEventMetadata();

Expand Down Expand Up @@ -754,6 +769,9 @@ Router = Router.extend({
* @returns {Function} - a function that can be given to the router.
*/
createChildViewHandler: createChildViewHandler,

// export this on 'router' for testing
ALWAYS_SHOWN_REACT_GROUPS,
});

export default Router;
65 changes: 60 additions & 5 deletions packages/fxa-content-server/app/tests/spec/lib/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -514,16 +514,71 @@ describe('lib/router', () => {
});

describe('React-related methods', () => {
beforeEach(() => {
const mockAlwaysShownReactGroups = ['simpleRoutes'];
sinon
.stub(router, 'ALWAYS_SHOWN_REACT_GROUPS')
.value(mockAlwaysShownReactGroups);
});
describe('showReactApp', () => {
beforeEach(() => {
sinon.spy(router, 'showReactApp');
});
it('returns true when routeName is included in react group route', () => {
assert.isTrue(router.showReactApp('cannot_create_account'));

describe('returns true', () => {
it('when routeName is included in react group route and user is in experiment', () => {
sinon.stub(router, 'isInReactExperiment').callsFake(() => true);
assert.isTrue(router.showReactApp('cannot_create_account'));
});

it('when routeName is in ALWAYS_SHOWN_REACT_GROUPS and user is not in experiment', () => {
assert.isTrue(router.showReactApp('legal'));
});

it('when routeName is a simpleRoute, relier is OAuth, and user is in experiment', () => {
sinon.stub(router, 'isInReactExperiment').callsFake(() => true);
const modifiedRelier = relier;
modifiedRelier.isOAuth = () => true;
router = new Router({
broker,
metrics,
notifier,
relier: modifiedRelier,
user,
window: windowMock,
config,
});

assert.isTrue(router.showReactApp('legal'));
});
});

it('returns false when routeName is not included in react group route', () => {
assert.isFalse(router.showReactApp('whatever'));
describe('returns false', () => {
it('when routeName is not included in react group route and user is in experiment', () => {
sinon.stub(router, 'isInReactExperiment').callsFake(() => true);
assert.isFalse(router.showReactApp('whatever'));
});

it('when user is not in experiment', () => {
assert.isFalse(router.showReactApp('reset_password'));
});

it('when routeName is not a simpleRoute, relier is OAuth, and user is in experiment', () => {
sinon.stub(router, 'isInReactExperiment').callsFake(() => true);
const modifiedRelier = relier;
modifiedRelier.isOAuth = () => true;
router = new Router({
broker,
metrics,
notifier,
relier: modifiedRelier,
user,
window: windowMock,
config,
});

assert.isFalse(router.showReactApp('reset_password'));
});
});
});
describe('createReactOrBackboneViewHandler', () => {
Expand Down Expand Up @@ -553,7 +608,7 @@ describe('lib/router', () => {
});
it('renders Backbone view when React conditions are not met', () => {
routeHandler = router.createReactOrBackboneViewHandler(
'cannot_create_account',
'reset_password',
CannotCreateAccountView,
additionalParams,
viewConstructorOptions
Expand Down
2 changes: 1 addition & 1 deletion packages/fxa-content-server/tests/functional.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module.exports = testsSettings.concat([
// new and flaky tests above here',
'tests/functional/500.js',
'tests/functional/back_button_after_start.js',
'tests/functional/cookies_disabled.js',
// 'tests/functional/cookies_disabled.js',
'tests/functional/email_domain_mx_validation.js',
'tests/functional/email_opt_in.js',
'tests/functional/force_auth.js',
Expand Down
14 changes: 10 additions & 4 deletions packages/fxa-content-server/tests/functional/lib/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -387,10 +387,16 @@ const clearContentServerState = thenify(function (options) {
// only load up the content server if we aren't
// already at the content server.
if (url.indexOf(CONTENT_SERVER) === -1 || options.force) {
return this.parent
.get(CONTENT_SERVER + 'clear')
.setFindTimeout(config.pageLoadTimeout)
.findById('fxa-clear-storage-header');
return (
this.parent
.get(CONTENT_SERVER + 'clear')
.setFindTimeout(config.pageLoadTimeout)
// TODO: intern doesn't have a "findByText" option so we've temporarily
// added this ID on the React 'clear' page because this page has been
// rolled out to 100% in prod. Remove this ID from the page once intern
// tests referring to this header are fully converted to Playwright.
.findById('clear-storage')
);
}
})

Expand Down
18 changes: 10 additions & 8 deletions packages/fxa-content-server/tests/functional/pages.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,35 @@
const { registerSuite } = intern.getInterface('object');
var url = intern._config.fxaContentRoot;

// Commented out pages here likely mean the React version is rolled out to 100%
// and we don't want to check these for `#stage header` selectors.
var pages = [
'',
'authorization',
'boom',
'cannot_create_account',
// 'cannot_create_account',
'choose_what_to_sync',
'clear',
// 'clear',
'complete_reset_password',
'complete_signin',
'confirm',
'confirm_reset_password',
'confirm_signin',
'connect_another_device',
'cookies_disabled',
// 'cookies_disabled',
// valid locale legal pages
'en/legal/terms',
'en/legal/privacy',
// 'en/legal/terms',
// 'en/legal/privacy',
'force_auth',
// invalid locale legal pages should be redirected to en-US
'invalid-locale/legal/terms',
'invalid-locale/legal/privacy',
'legal',
// 'legal',
// legal are all redirected to the language detected
// by sniffing headers, barring that, using en-US as
// the fallback.
'legal/terms',
'legal/privacy',
// 'legal/terms',
// 'legal/privacy',
'non_existent',
'oauth',
'oauth/force_auth',
Expand Down
6 changes: 6 additions & 0 deletions packages/fxa-content-server/tests/functional/sign_up.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ registerSuite('signup here', {
},

'visiting the pp links saves information for return': function () {
// Skip for now, we'll need to account for this in the React signup epic
// if we want to keep this functionality
this.skip();
return testRepopulateFields.call(
this,
'/legal/terms',
Expand All @@ -197,6 +200,9 @@ registerSuite('signup here', {
},

'visiting the tos links saves information for return': function () {
// Skip for now, we'll need to account for this in the React signup epic
// if we want to keep this functionality
this.skip();
return testRepopulateFields.call(
this,
'/legal/privacy',
Expand Down
11 changes: 7 additions & 4 deletions packages/fxa-settings/src/pages/CannotCreateAccount/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@ const CannotCreateAccount = (_: RouteComponentProps) => {
usePageViewEvent(viewName, REACT_ENTRYPOINT);
return (
<AppLayout>
<CardHeader
headingText="Cannot create account"
headingTextFtlId="cannot-create-account-header"
/>
{/* Span is temporary until sign up tests are converted to playwright */}
<span id="fxa-cannot-create-account-header">
<CardHeader
headingText="Cannot create account"
headingTextFtlId="cannot-create-account-header"
/>
</span>
<FtlMsg id="cannot-create-account-requirements">
<p className="text-sm mb-9">
You must meet certain age requirements to create a Firefox account.
Expand Down
8 changes: 7 additions & 1 deletion packages/fxa-settings/src/pages/Clear/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ const Clear = (_: RouteComponentProps) => {

return (
<AppLayout>
<h1 className="card-header">Browser storage is cleared</h1>
{/* TODO: intern doesn't have a "findByText" option so we've
temporarily added this ID because intern tests still refer to this page
and it's been rolled out to 100% in prod. Remove this ID once intern tests
referring to this header are fully converted to Playwright. */}
<h1 className="card-header" id="clear-storage">
Browser storage is cleared
</h1>
</AppLayout>
);
};
Expand Down

0 comments on commit 8fbea9c

Please sign in to comment.