Merge pull request #3341 from mozilla/issue-3079-sync-preferences-verification-page

feat(client): Add a "Sync Preferences" button for fx-desktop-v3 broker.

r=@philbooth

Thanks @philbooth!
This commit is contained in:
Shane Tomlinson 2016-01-12 14:23:20 +00:00
Родитель 84206c73c5 7fd285558f
Коммит fa6dfb9119
14 изменённых файлов: 272 добавлений и 29 удалений

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

@ -34,6 +34,7 @@ define(function (require, exports, module) {
var FxaClient = require('lib/fxa-client');
var FxDesktopV1AuthenticationBroker = require('models/auth_brokers/fx-desktop-v1');
var FxDesktopV2AuthenticationBroker = require('models/auth_brokers/fx-desktop-v2');
var FxDesktopV3AuthenticationBroker = require('models/auth_brokers/fx-desktop-v3');
var FxFennecV1AuthenticationBroker = require('models/auth_brokers/fx-fennec-v1');
var FxiOSV1AuthenticationBroker = require('models/auth_brokers/fx-ios-v1');
var FxiOSV2AuthenticationBroker = require('models/auth_brokers/fx-ios-v2');
@ -372,6 +373,11 @@ define(function (require, exports, module) {
relier: this._relier,
window: this._window
});
} else if (this._isFxDesktopV3()) {
this._authenticationBroker = new FxDesktopV3AuthenticationBroker({
relier: this._relier,
window: this._window
});
} else if (this._isFxDesktopV2()) {
this._authenticationBroker = new FxDesktopV2AuthenticationBroker({
relier: this._relier,
@ -651,6 +657,10 @@ define(function (require, exports, module) {
return this._isContext(Constants.FX_DESKTOP_V1_CONTEXT);
},
_isFxDesktopV3: function () {
return this._isContext(Constants.FX_DESKTOP_V3_CONTEXT);
},
_isFxDesktopV2: function () {
// A user is signing into sync from within an iframe on a trusted
// web page. Automatically speak version 2 using WebChannels.

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

@ -30,6 +30,7 @@ define(function (require, exports, module) {
DIRECT_CONTEXT: 'direct',
FX_DESKTOP_V1_CONTEXT: 'fx_desktop_v1',
FX_DESKTOP_V2_CONTEXT: 'fx_desktop_v2',
FX_DESKTOP_V3_CONTEXT: 'fx_desktop_v3',
FX_FENNEC_V1_CONTEXT: 'fx_fennec_v1',
FX_IOS_V1_CONTEXT: 'fx_ios_v1',
FX_IOS_V2_CONTEXT: 'fx_ios_v2',

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

@ -0,0 +1,29 @@
/* 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/. */
/**
* A variant of the FxSync broker that speaks "v3" of the protocol.
*
* Enable syncPreferencesNotification on the verification complete screen.
*/
define(function (require, exports, module) {
'use strict';
var _ = require('underscore');
var FxDesktopV2AuthenticationBroker = require('./fx-desktop-v2');
var proto = FxDesktopV2AuthenticationBroker.prototype;
var FxDesktopV3AuthenticationBroker = FxDesktopV2AuthenticationBroker.extend({
defaultCapabilities: _.extend({}, proto.defaultCapabilities, {
syncPreferencesNotification: true
}),
type: 'fx-desktop-v3'
});
module.exports = FxDesktopV3AuthenticationBroker;
});

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

@ -20,10 +20,6 @@ define(function (require, exports, module) {
var FxFennecV1AuthenticationBroker = FxSyncWebChannelAuthenticationBroker.extend({
type: 'fx-fennec-v1',
commands: _.extend({}, proto.commands, {
SYNC_PREFERENCES: 'fxaccounts:sync_preferences'
}),
defaultCapabilities: _.extend({}, proto.defaultCapabilities, {
chooseWhatToSyncCheckbox: false,
chooseWhatToSyncWebV1: {
@ -55,16 +51,6 @@ define(function (require, exports, module) {
});
}
});
},
/**
* Notify the browser that it should open sync preferences
*
* @method openSyncPreferences
* @returns {promise} resolves when notification is sent.
*/
openSyncPreferences: function () {
return this.send(this.getCommand('SYNC_PREFERENCES'));
}
});

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

@ -22,7 +22,8 @@ define(function (require, exports, module) {
CHANGE_PASSWORD: 'fxaccounts:change_password',
DELETE_ACCOUNT: 'fxaccounts:delete_account',
LOADED: 'fxaccounts:loaded',
LOGIN: 'fxaccounts:login'
LOGIN: 'fxaccounts:login',
SYNC_PREFERENCES: 'fxaccounts:sync_preferences'
},
createChannel: function () {

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

@ -224,6 +224,21 @@ define(function (require, exports, module) {
loginData.verified = !! loginData.verified;
loginData.verifiedCanLinkAccount = !! this._verifiedCanLinkAccount;
return loginData;
},
/**
* Notify the browser that it should open sync preferences
*
* @method openSyncPreferences
* @param {string} entryPoint - where Sync Preferences is opened from
* @returns {promise} resolves when notification is sent.
*/
openSyncPreferences: function (entryPoint) {
if (this.hasCapability('syncPreferencesNotification')) {
return this.send(this.getCommand('SYNC_PREFERENCES'), {
entryPoint: entryPoint
});
}
}
});

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

@ -120,7 +120,8 @@ define(function (require, exports, module) {
_submitForSyncPreferences: function () {
var self = this;
return this.metrics.flush().then(function () {
return self.broker.openSyncPreferences();
var entryPoint = 'fxa:' + self.getViewName();
return self.broker.openSyncPreferences(entryPoint);
});
},

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

@ -0,0 +1,32 @@
/* 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';
var chai = require('chai');
var FxDesktopV3AuthenticationBroker = require('models/auth_brokers/fx-desktop-v3');
var WindowMock = require('../../../mocks/window');
var assert = chai.assert;
describe('models/auth_brokers/fx-desktop-v3', function () {
var broker;
var windowMock;
before(function () {
windowMock = new WindowMock();
broker = new FxDesktopV3AuthenticationBroker({
window: windowMock
});
});
describe('capabilities', function () {
it('has the `syncPreferencesNotification` capability', function () {
assert.isTrue(broker.hasCapability('syncPreferencesNotification'));
});
});
});
});

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

@ -129,15 +129,6 @@ define(function (require, exports, module) {
});
});
});
describe('openSyncPreferences', function () {
it('sends the `fxaccounts:sync_preferences` message', function () {
return broker.openSyncPreferences()
.then(function () {
assert.isTrue(broker.send.calledWith('fxaccounts:sync_preferences'));
});
});
});
});
});

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

@ -34,7 +34,8 @@ define(function (require, exports, module) {
CHANGE_PASSWORD: 'change_password',
DELETE_ACCOUNT: 'delete_account',
LOADED: 'loaded',
LOGIN: 'login'
LOGIN: 'login',
SYNC_PREFERENCES: 'sync_preferences'
},
window: windowMock
}, options));
@ -328,6 +329,40 @@ define(function (require, exports, module) {
assert.equal(broker.getCommand('LOGIN'), 'login');
});
});
describe('openSyncPreferences', function () {
beforeEach(function () {
broker.unsetCapability('syncPreferencesNotification');
sinon.spy(broker, 'send');
});
describe('without the `syncPreferencesNotification` capability', function () {
beforeEach(function () {
return broker.openSyncPreferences('fxa:signup-complete');
});
it('does not send the `sync_preferences` message', function () {
assert.isFalse(broker.send.calledWith('sync_preferences'));
});
});
describe('with the `syncPreferencesNotification` capability', function () {
beforeEach(function () {
broker.setCapability('syncPreferencesNotification', true);
return broker.openSyncPreferences('fxa:signup-complete');
});
it('sends the `sync_preferences` message', function () {
assert.isTrue(broker.send.calledWith(
'sync_preferences',
{
entryPoint: 'fxa:signup-complete'
}
));
});
});
});
});
});

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

@ -155,6 +155,7 @@ function (Translator, Session) {
'../tests/spec/models/auth_brokers/first-run',
'../tests/spec/models/auth_brokers/fx-desktop-v1',
'../tests/spec/models/auth_brokers/fx-desktop-v2',
'../tests/spec/models/auth_brokers/fx-desktop-v3',
'../tests/spec/models/auth_brokers/fx-fennec-v1',
'../tests/spec/models/auth_brokers/fx-ios-v1',
'../tests/spec/models/auth_brokers/fx-ios-v2',

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

@ -125,7 +125,7 @@ Halt after the user signs in, do not redirect to the settings page.
If the user is migrating their Sync account from "old sync" to "new sync", specify which sync they are migrating from.
#### When to specify
Only available if `context` equals `fx_desktop_v1`, `fx_desktop_v2`, `fx_fennec_v1`, `fx_ios_v1`, or `iframe`.
Only available if `context` equals `fx_desktop_v1`, `fx_desktop_v2`, `fx_desktop_v3`, `fx_fennec_v1`, `fx_ios_v1`, or `iframe`.
* /signin
* /signup
@ -137,7 +137,7 @@ Specify which non-OAuth service a user is signing in to.
* `sync`
#### When to specify
Only available if `context` equals `fx_desktop_v1`, `fx_desktop_v2`, `fx_fennec_v1`, `fx_ios_v1`, or `iframe`.
Only available if `context` equals `fx_desktop_v1`, `fx_desktop_v2`, `fx_desktop_v3`, `fx_fennec_v1`, `fx_ios_v1`, or `iframe`.
* /signin
* /signup
@ -164,10 +164,16 @@ Specify an alternate context in which Firefox Accounts is being run, if not as a
Firefox Desktop using CustomEvents.
* `fx_desktop_v2` - Firefox Accounts is being used to sign in to Sync on
Firefox Desktop using WebChannels.
* `fx_desktop_v3` - Firefox Accounts is being used to sign in to Sync on
Firefox Desktop using WebChannels. Adds thh `syncPreferencesNotification`
capability
* `fx_fennec_v1` - Firefox Accounts is being used to sign in to Sync on
Firefox for Android using CustomEvents.
Firefox for Android using WebChannels.
* `fx_ios_v1` - Firefox Accounts is being used to sign in to Sync on Firefox
for iOS using CustomEvents.
* `fx_ios_v2` - Firefox Accounts is being used to sign in to Sync on Firefox
for iOS using CustomEvents. Adds `chooseWhatToSyncWebV1` and
`syncPreferencesNotification` capabilities.
* `iframe` - Firefox Accounts is displayed in an iframe.
### `email`

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

@ -11,6 +11,7 @@ define([
'./functional/complete_sign_up',
'./functional/sync_sign_up',
'./functional/sync_v2_sign_up',
'./functional/sync_v3_sign_up',
'./functional/firstrun_sign_up',
'./functional/firstrun_sign_in',
'./functional/fx_ios_v1_sign_in',

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

@ -0,0 +1,134 @@
/* 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([
'intern',
'intern!object',
'intern/chai!assert',
'require',
'tests/lib/helpers',
'tests/functional/lib/helpers'
], function (intern, registerSuite, assert, require, TestHelpers, FunctionalHelpers) {
var config = intern.config;
var PAGE_URL = config.fxaContentRoot + 'signup?context=fx_desktop_v3&service=sync';
var SIGNIN_URL = config.fxaContentRoot + 'signin';
var email;
var PASSWORD = '12345678';
var listenForFxaCommands = FunctionalHelpers.listenForWebChannelMessage;
var respondToWebChannelMessage = FunctionalHelpers.respondToWebChannelMessage;
registerSuite({
name: 'Firefox Desktop Sync v3 sign_up',
beforeEach: function () {
email = TestHelpers.createEmail();
return FunctionalHelpers.clearBrowserState(this);
},
afterEach: function () {
var self = this;
return FunctionalHelpers.clearBrowserState(this)
.then(function () {
// ensure the next test suite (bounced_email) loads a fresh
// signup page. If a fresh signup page is not forced, the
// bounced_email tests try to sign up using the Sync broker,
// resulting in a channel timeout.
return self.remote
.get(require.toUrl(SIGNIN_URL))
.findByCssSelector('#fxa-signin-header')
.end();
});
},
'sign up, verify same browser': function () {
var self = this;
return FunctionalHelpers.openPage(this, PAGE_URL, '#fxa-signup-header')
.execute(listenForFxaCommands)
.then(respondToWebChannelMessage(self, 'fxaccounts:can_link_account', { ok: true } ))
.then(function () {
return FunctionalHelpers.fillOutSignUp(self, email, PASSWORD);
})
.then(FunctionalHelpers.testIsBrowserNotified(self, 'fxaccounts:can_link_account'))
.then(FunctionalHelpers.noSuchBrowserNotification(self, 'fxaccounts:login'))
// user should be transitioned to the choose what to Sync page
.findByCssSelector('#fxa-choose-what-to-sync-header')
.end()
.findByCssSelector('button[type=submit]')
.click()
.end()
// user should be transitioned to the "go confirm your address" page
.findByCssSelector('#fxa-confirm-header')
.end()
// the login message is only sent after the sync preferences screen
// has been cleared.
.then(FunctionalHelpers.testIsBrowserNotified(self, 'fxaccounts:login', function (data) {
assert.isTrue(data.customizeSync);
assert.equal(data.email, email);
assert.ok(data.keyFetchToken);
assert.ok(data.sessionToken);
assert.ok(data.uid);
assert.ok(data.unwrapBKey);
assert.isFalse(data.verified);
assert.isTrue(data.verifiedCanLinkAccount);
}))
// verify the user
.then(function () {
return FunctionalHelpers.openVerificationLinkInNewTab(
self, email, 0);
})
.switchToWindow('newwindow')
// user should be redirected to "Success!" screen.
// In real life, the original browser window would show
// a "welcome to sync!" screen that has a manage button
// on it, and this screen should show the FxA success screen.
.findById('fxa-sign-up-complete-header')
.end()
.findByCssSelector('.account-ready-service')
.getVisibleText()
.then(function (text) {
assert.ok(text.indexOf('Firefox Sync') > -1);
})
.end()
// attempt to open sync preferences
.findByCssSelector('#sync-preferences')
.click()
.end()
.then(FunctionalHelpers.testIsBrowserNotified(self, 'fxaccounts:sync_preferences', function (data) {
assert.equal(data.entryPoint, 'fxa:signup-complete');
}))
.closeCurrentWindow()
// switch to the original window, it should not transition.
.switchToWindow('')
.end()
// We do not expect the verification poll to occur. The poll
// will take a few seconds to complete if it erroneously occurs.
// Add an affordance just in case the poll happens unexpectedly.
.sleep(5000)
.then(FunctionalHelpers.visibleByQSA('#fxa-confirm-header'))
.end();
}
});
});