blob: 1dd431ca2c686d5a7fe49c99f903f328cf3f6a62 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
suite('Multidevice', function() {
let multidevicePage = null;
let browserProxy = null;
let ALL_MODES;
/**
* Sets pageContentData via WebUI Listener and flushes.
* @param {!MultiDevicePageContentData}
*/
function setPageContentData(newPageContentData) {
cr.webUIListenerCallback(
'settings.updateMultidevicePageContentData', newPageContentData);
Polymer.dom.flush();
}
/**
* Sets pageContentData to the specified mode. If it is a mode corresponding
* to a set host, it will set the hostDeviceName to the provided name or else
* default to multidevice.HOST_DEVICE.
* @param {settings.MultiDeviceSettingsMode} newMode
* @param {string=} opt_newHostDeviceName Overrides default if |newMode|
* corresponds to a set host.
*/
function setHostData(newMode, opt_newHostDeviceName) {
setPageContentData(
multidevice.createFakePageContentData(newMode, opt_newHostDeviceName));
}
function setSuiteState(newState) {
setPageContentData(Object.assign(
{}, multidevicePage.pageContentData, {betterTogetherState: newState}));
}
function setSmartLockState(newState) {
setPageContentData(Object.assign(
{}, multidevicePage.pageContentData, {smartLockState: newState}));
}
/**
* @param {!settings.MultiDeviceFeature} feature The feature to change.
* @param {boolean} enabled Whether to enable or disable the feature.
* @param {boolean} authRequired Whether authentication is required for the
* change.
* @return {!Promise} Promise which resolves when the state change has been
* verified.
* @private
*/
function simulateFeatureStateChangeRequest(feature, enabled, authRequired) {
// When the user requets a feature state change, an event with the relevant
// details is handled.
multidevicePage.fire(
'feature-toggle-clicked', {feature: feature, enabled: enabled});
Polymer.dom.flush();
if (authRequired) {
assertTrue(multidevicePage.showPasswordPromptDialog_);
// Simulate the user entering a valid password, then closing the dialog.
multidevicePage.fire('auth-token-changed', {value: 'validAuthToken'});
// Simulate closing the password prompt dialog
multidevicePage.$$('#multidevicePasswordPrompt').fire('close');
Polymer.dom.flush();
} else {
assertFalse(multidevicePage.showPasswordPromptDialog_);
}
return browserProxy.whenCalled('setFeatureEnabledState').then(params => {
assertEquals(feature, params[0]);
assertEquals(enabled, params[1]);
// Reset the resolver so that setFeatureEnabledState() can be called
// multiple times in a test.
browserProxy.resetResolver('setFeatureEnabledState');
});
}
suiteSetup(function() {
ALL_MODES = Object.values(settings.MultiDeviceSettingsMode);
});
setup(function() {
PolymerTest.clearBody();
browserProxy = new multidevice.TestMultideviceBrowserProxy();
settings.MultiDeviceBrowserProxyImpl.instance_ = browserProxy;
multidevicePage = document.createElement('settings-multidevice-page');
assertTrue(!!multidevicePage);
document.body.appendChild(multidevicePage);
return browserProxy.whenCalled('getPageContentData');
});
teardown(function() {
multidevicePage.remove();
});
const getLabel = () => multidevicePage.$$('#multidevice-label').textContent;
const getSubpage = () => multidevicePage.$$('settings-multidevice-subpage');
test('clicking setup shows multidevice setup dialog', function() {
setHostData(settings.MultiDeviceSettingsMode.NO_HOST_SET);
const button = multidevicePage.$$('paper-button');
assertTrue(!!button);
button.click();
return browserProxy.whenCalled('showMultiDeviceSetupDialog');
});
test('headings render based on mode and host', function() {
for (const mode of ALL_MODES) {
setHostData(mode);
assertEquals(
multidevicePage.isHostSet(), getLabel() === multidevice.HOST_DEVICE);
}
});
test('changing host device changes header', function() {
setHostData(settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED);
assertEquals(getLabel(), multidevice.HOST_DEVICE);
const anotherHost = 'Super Duper ' + multidevice.HOST_DEVICE;
setHostData(
settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED, anotherHost);
assertEquals(getLabel(), anotherHost);
});
test('item is actionable if and only if a host is set', function() {
for (const mode of ALL_MODES) {
setHostData(mode);
assertEquals(
multidevicePage.isHostSet(),
!!multidevicePage.$$('#multidevice-item').hasAttribute('actionable'));
}
});
test(
'clicking item with verified host opens subpage with features',
function() {
setHostData(settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED);
assertFalse(!!getSubpage());
multidevicePage.$$('#multidevice-item').click();
assertTrue(!!getSubpage());
assertTrue(!!getSubpage().$$('settings-multidevice-feature-item'));
});
test(
'clicking item with unverified set host opens subpage without features',
function() {
setHostData(
settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_VERIFICATION,
multidevice.HOST_DEVICE);
assertFalse(!!getSubpage());
multidevicePage.$$('#multidevice-item').click();
assertTrue(!!getSubpage());
assertFalse(!!getSubpage().$$('settings-multidevice-feature-item'));
});
test('policy prohibited suite shows policy indicator', function() {
setHostData(settings.MultiDeviceSettingsMode.NO_ELIGIBLE_HOSTS);
assertFalse(!!multidevicePage.$$('cr-policy-indicator'));
// Prohibit suite by policy.
setSuiteState(settings.MultiDeviceFeatureState.PROHIBITED_BY_POLICY);
assertTrue(!!multidevicePage.$$('cr-policy-indicator'));
// Reallow suite.
setSuiteState(settings.MultiDeviceFeatureState.DISABLED_BY_USER);
assertFalse(!!multidevicePage.$$('cr-policy-indicator'));
});
test('Disabling features never requires authentication', () => {
const Feature = settings.MultiDeviceFeature;
const disableFeatureFn = feature => {
return simulateFeatureStateChangeRequest(
feature, false /* enabled */, false /* authRequired */);
};
return disableFeatureFn(Feature.BETTER_TOGETHER_SUITE)
.then(() => {
return disableFeatureFn(Feature.INSTANT_TETHERING);
})
.then(() => {
return disableFeatureFn(Feature.MESSAGES);
})
.then(() => {
return disableFeatureFn(Feature.SMART_LOCK);
});
});
test('Enabling some features requires authentication; others do not', () => {
const Feature = settings.MultiDeviceFeature;
const FeatureState = settings.MultiDeviceFeatureState;
const enableFeatureWithoutAuthFn = feature => {
return simulateFeatureStateChangeRequest(
feature, true /* enabled */, false /* authRequired */);
};
const enableFeatureWithAuthFn = feature => {
return simulateFeatureStateChangeRequest(
feature, true /* enabled */, true /* authRequired */);
};
// Start out with SmartLock being disabled by the user. This means that
// the first attempt to enable BETTER_TOGETHER_SUITE below will not
// require authentication.
setSmartLockState(FeatureState.DISABLED_BY_USER);
// INSTANT_TETHERING requires no authentication.
return enableFeatureWithoutAuthFn(Feature.INSTANT_TETHERING)
.then(() => {
// MESSAGES requires no authentication.
return enableFeatureWithoutAuthFn(Feature.MESSAGES);
})
.then(() => {
// BETTER_TOGETHER_SUITE requires no authentication normally.
return enableFeatureWithoutAuthFn(Feature.BETTER_TOGETHER_SUITE);
})
.then(() => {
// BETTER_TOGETHER_SUITE requires authentication when SmartLock's
// state is UNAVAILABLE_SUITE_DISABLED.
setSmartLockState(FeatureState.UNAVAILABLE_SUITE_DISABLED);
return enableFeatureWithAuthFn(Feature.BETTER_TOGETHER_SUITE);
})
.then(() => {
// BETTER_TOGETHER_SUITE requires authentication when SmartLock's
// state is UNAVAILABLE_INSUFFICIENT_SECURITY.
setSmartLockState(FeatureState.UNAVAILABLE_INSUFFICIENT_SECURITY);
return enableFeatureWithAuthFn(Feature.BETTER_TOGETHER_SUITE);
})
.then(() => {
// SMART_LOCK always requires authentication.
return enableFeatureWithAuthFn(Feature.SMART_LOCK);
});
});
});