Commit 99822499 authored by Jordy Greenblatt's avatar Jordy Greenblatt Committed by Commit Bot

[CrOS MultiDevice]: Added UIPage structure.

I added the UIPage layer which is the shared structure between all the
WebUI pages. This involved fleshing out the ButtonNavigationBehavior to
allow links appearing in the UIPage to have page-specific customized
callbacks for links appearing in the messages (and the behavior was
accordingly renamed UiPageContainerBehavior).

To make sure that the structure was functional, I added links into the
placeholder text for the pages' messages where they are supposed to
appear in the actual text and tested that they can access custom
callbacks.

Cq-Include-Trybots: master.tryserver.chromium.linux:closure_compilation
Change-Id: I4963c9e573e83ea4c699920639cfe197fe6e1613
Reviewed-on: https://chromium-review.googlesource.com/1029531Reviewed-by: default avatarKyle Horimoto <khorimoto@chromium.org>
Commit-Queue: Jordy Greenblatt <jordynass@chromium.org>
Cr-Commit-Position: refs/heads/master@{#554203}
parent 95bff1bf
......@@ -132,12 +132,30 @@
<message name="IDS_MULTIDEVICE_SETUP_DIALOG_TITLE" desc="Title for the MultiDevice setup dialog, which allows users to enable features which involve communication between multiple devices (e.g., a Chromebook and a phone)." translateable="false">
MultiDevice Setup
</message>
<message name="IDS_MULTIDEVICE_SETUP_ACCEPT_LABEL" desc="Label for button to accept conditions and begin MultiDevice setup workflow.">
<message name="IDS_MULTIDEVICE_SETUP_ACCEPT_LABEL" desc="Label for button to accept conditions and begin MultiDevice setup workflow." translateable="false">
Accept
</message>
<message name="IDS_MULTIDEVICE_SETUP_TRY_AGAIN_LABEL" desc="Label for button to retry setup upon failure.">
<message name="IDS_MULTIDEVICE_SETUP_TRY_AGAIN_LABEL" desc="Label for button to retry setup upon failure." translateable="false">
Try again
</message>
<message name="IDS_MULTIDEVICE_SETUP_SETUP_FAILED_PAGE_HEADER" desc="Header for failed setup page." translateable="false">
Could not connect to phone (PlAcEhOlDeR tExT!!)
</message>
<message name="IDS_MULTIDEVICE_SETUP_SETUP_FAILED_PAGE_MESSAGE" desc="Message for failed setup page." translateable="false">
PlAcEhOlDeR tExT!! This is a paragraph about an error. Blah blah blah. Something went wrong. Whomp whomp whomp.
</message>
<message name="IDS_MULTIDEVICE_SETUP_SETUP_SUCCEEDED_PAGE_HEADER" desc="Header for successful setup page." translateable="false">
You're all set! (PlAcEhOlDeR tExT!!)
</message>
<message name="IDS_MULTIDEVICE_SETUP_SETUP_SUCCEEDED_PAGE_MESSAGE" desc="Message for successful setup page." translateable="false">
PlAcEhOlDeR tExT!! This String includes a link with the text &lt;a id="settings-link"&gt;Settings&lt;/a&gt; that opens the settings page. Blah blah blah.
</message>
<message name="IDS_MULTIDEVICE_SETUP_START_SETUP_PAGE_HEADER" desc="Header for welcome page." translateable="false">
Better together (PlAcEhOlDeR tExT!!)
</message>
<message name="IDS_MULTIDEVICE_SETUP_START_SETUP_PAGE_MESSAGE" desc="Message for welcome page." translateable="false">
PlAcEhOlDeR tExT!! This String includes a link with the text &lt;a id="terms-and-conditions-link" href="chrome://foo-bar"&gt;Terms and Conditions&lt;/a&gt; that opens a browser window to that info. Blah blah blah.
</message>
<!-- File Manager -->
<message name="IDS_FILE_SYSTEM_PROVIDER_UNRESPONSIVE_WARNING" desc="A warning shown in a notification that an operation is taking longer than expected.">
......
// 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.
/** @polymerBehavior */
const ButtonNavigationBehaviorImpl = {
properties: {
/**
* ID for forward button label, which must be translated for display.
*
* Undefined if the visible page has no forward-navigation button.
*
* @type {string|undefined}
*/
forwardButtonTextId: String,
/**
* ID for backward button label, which must be translated for display.
*
* Undefined if the visible page has no backward-navigation button.
*
* @type {string|undefined}
*/
backwardButtonTextId: String,
/**
* Translated text to display on the forward-naviation button.
*
* Undefined if the visible page has no forward-navigation button.
*
* @type {string|undefined}
*/
forwardButtonText: {
type: String,
computed: 'computeButtonText_(forwardButtonTextId)',
},
/**
* Translated text to display on the backward-naviation button.
*
* Undefined if the visible page has no backward-navigation button.
*
* @type {string|undefined}
*/
backwardButtonText: {
type: String,
computed: 'computeButtonText_(backwardButtonTextId)',
},
},
/**
* @param {string} buttonTextId Key for the localized string to appear on a
* button.
* @return {string|undefined} The localized string corresponding to the key
* buttonTextId. Return value is undefined if buttonTextId is not a key
* for any localized string. Note: this includes the case in which
* buttonTextId is undefined.
* @private
*/
computeButtonText_(buttonTextId) {
return this.i18nExists(buttonTextId) ? this.i18n(buttonTextId) : undefined;
},
};
/** @polymerBehavior */
const ButtonNavigationBehavior = [
I18nBehavior,
ButtonNavigationBehaviorImpl,
];
......@@ -10,15 +10,6 @@
['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
'target_name' : 'button_navigation_behavior',
'dependencies' : [
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
],
'includes' :
['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
'target_name' : 'multidevice_setup',
'dependencies' : [
......@@ -35,7 +26,7 @@
{
'target_name' : 'setup_failed_page',
'dependencies' : [
'button_navigation_behavior',
'ui_page_container_behavior',
],
'includes' :
['../../../../../third_party/closure_compiler/compile_js2.gypi'],
......@@ -44,7 +35,7 @@
{
'target_name' : 'setup_succeeded_page',
'dependencies' : [
'button_navigation_behavior',
'ui_page_container_behavior',
],
'includes' :
['../../../../../third_party/closure_compiler/compile_js2.gypi'],
......@@ -53,7 +44,17 @@
{
'target_name' : 'start_setup_page',
'dependencies' : [
'button_navigation_behavior',
'ui_page_container_behavior',
],
'includes' :
['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
'target_name' : 'ui_page_container_behavior',
'dependencies' : [
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
],
'includes' :
['../../../../../third_party/closure_compiler/compile_js2.gypi'],
......
......@@ -3,8 +3,6 @@
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-pages/iron-pages.html">
<link rel="import" href="button_bar.html">
<link rel="import" href="button_navigation_behavior.html">
<link rel="import" href="setting_up_page.html">
<link rel="import" href="setup_failed_page.html">
<link rel="import" href="setup_succeeded_page.html">
<link rel="import" href="start_setup_page.html">
......@@ -12,7 +10,6 @@
<dom-module id="multidevice-setup">
<template>
<iron-pages
id="pages"
attr-for-selected="is"
selected="[[visiblePageName_]]"
selected-item="{{visiblePage_}}">
......
......@@ -18,12 +18,6 @@
<structure name="IDR_MULTIDEVICE_SETUP_BUTTON_BAR_JS"
file="button_bar.js"
type="chrome_html" />
<structure name="IDR_MULTIDEVICE_SETUP_BUTTON_NAVIGATION_BEHAVIOR_HTML"
file="button_navigation_behavior.html"
type="chrome_html" />
<structure name="IDR_MULTIDEVICE_SETUP_BUTTON_NAVIGATION_BEHAVIOR_JS"
file="button_navigation_behavior.js"
type="chrome_html" />
<structure name="IDR_MULTIDEVICE_SETUP_I18N_SETUP_HTML"
file="i18n_setup.html"
type="chrome_html" />
......@@ -56,6 +50,18 @@
<structure name="IDR_MULTIDEVICE_SETUP_START_SETUP_PAGE_JS"
file="start_setup_page.js"
type="chrome_html" />
<structure name="IDR_MULTIDEVICE_SETUP_UI_PAGE_CONTAINER_BEHAVIOR_HTML"
file="ui_page_container_behavior.html"
type="chrome_html" />
<structure name="IDR_MULTIDEVICE_SETUP_UI_PAGE_CONTAINER_BEHAVIOR_JS"
file="ui_page_container_behavior.js"
type="chrome_html" />
<structure name="IDR_MULTIDEVICE_SETUP_UI_PAGE_HTML"
file="ui_page.html"
type="chrome_html" />
<structure name="IDR_MULTIDEVICE_SETUP_UI_PAGE_JS"
file="ui_page.js"
type="chrome_html" />
</structures>
</release>
</grit>
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="button_navigation_behavior.html">
<link rel="import" href="ui_page_container_behavior.html">
<link rel="import" href="ui_page.html">
<dom-module id="setup-failed-page">
<template>
--------------Setup Failed Placeholder Text--------------
<ui-page header-text="[[headerText]]">
<span slot="message" inner-h-t-m-l="[[messageHtml]]"></span>
<div slot="additional-content">
This is empty... (PlAcEhOlDeR tExT!!)
</div>
</ui-page>
</template>
<script src="setup_failed_page.js"></script>
</dom-module>
......@@ -6,24 +6,32 @@ Polymer({
is: 'setup-failed-page',
properties: {
/**
* Overriden from ButtonNavigationBehavior
*/
/** Overridden from UiPageContainerBehavior. */
forwardButtonTextId: {
type: String,
value: 'tryAgain',
},
/**
* Overriden from ButtonNavigationBehavior
*/
/** Overridden from UiPageContainerBehavior. */
backwardButtonTextId: {
type: String,
value: 'cancel',
},
/** Overridden from UiPageContainerBehavior. */
headerId: {
type: String,
value: 'setupFailedPageHeader',
},
/** Overridden from UiPageContainerBehavior. */
messageId: {
type: String,
value: 'setupFailedPageMessage',
},
},
behaviors: [
ButtonNavigationBehavior,
UiPageContainerBehavior,
],
});
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="button_navigation_behavior.html">
<link rel="import" href="ui_page.html">
<link rel="import" href="ui_page_container_behavior.html">
<dom-module id="setup-succeeded-page">
<template>
--------------Setup Succeeded Placeholder Text--------------
<ui-page header-text="[[headerText]]">
<span slot="message" inner-h-t-m-l="[[messageHtml]]"></span>
<div slot="additional-content">
This is empty... (PlAcEhOlDeR tExT!!)
</div>
</ui-page>
</template>
<script src="setup_succeeded_page.js"></script>
</dom-module>
......@@ -6,16 +6,41 @@ Polymer({
is: 'setup-succeeded-page',
properties: {
/**
* Overriden from ButtonNavigationBehavior
*/
/** Overridden from UiPageContainerBehavior. */
forwardButtonTextId: {
type: String,
value: 'done',
},
/** Overridden from UiPageContainerBehavior. */
headerId: {
type: String,
value: 'setupSucceededPageHeader',
},
/** Overridden from UiPageContainerBehavior. */
messageId: {
type: String,
value: 'setupSucceededPageMessage',
},
},
behaviors: [
ButtonNavigationBehavior,
UiPageContainerBehavior,
],
/** @private */
openSettings_: function() {
// TODO(jordynass): Open MultiDevice settings when that page is built.
console.log('Opening MultiDevice Settings');
// This method is just for testing that the method was called
this.fire('settings-opened');
},
/** @override */
ready: function() {
let linkElement = this.$$('#settings-link');
linkElement.setAttribute('href', '#');
linkElement.addEventListener('click', () => this.openSettings_());
}
});
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="button_navigation_behavior.html">
<link rel="import" href="ui_page.html">
<link rel="import" href="ui_page_container_behavior.html">
<dom-module id="start-setup-page">
<template>
--------------Start Setup Placeholder Text--------------
<ui-page header-text="[[headerText]]">
<span slot="message" inner-h-t-m-l="[[messageHtml]]"></span>
<div slot="additional-content">
This is a dropdown or a spinner... (PlAcEhOlDeR tExT!!)
</div>
</ui-page>
</template>
<script src="start_setup_page.js"></script>
</dom-module>
......@@ -6,24 +6,32 @@ Polymer({
is: 'start-setup-page',
properties: {
/**
* Overriden from ButtonNavigationBehavior
*/
/** Overridden from UiPageContainerBehavior. */
forwardButtonTextId: {
type: String,
value: 'accept',
},
/**
* Overriden from ButtonNavigationBehavior
*/
/** Overridden from UiPageContainerBehavior. */
backwardButtonTextId: {
type: String,
value: 'cancel',
},
/** Overridden from UiPageContainerBehavior. */
headerId: {
type: String,
value: 'startSetupPageHeader',
},
/** Overridden from UiPageContainerBehavior. */
messageId: {
type: String,
value: 'startSetupPageMessage',
},
},
behaviors: [
ButtonNavigationBehavior,
UiPageContainerBehavior,
],
});
<link rel="import" href="chrome://resources/html/polymer.html">
<dom-module id="ui-page">
<template>
<div>[[headerText]]</div>
<slot name="message"></slot>
<slot name="additional-content"></slot>
</template>
<script src="ui_page.js"></script>
</dom-module>
// 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.
/**
* An element that encapsulates the structure common to all pages in the WebUI.
*/
Polymer({
is: 'ui-page',
properties: {
/**
* Main heading for the page.
*
* @type {string}
*/
headerText: String,
},
});
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<script src="button_navigation_behavior.js"></script>
<script src="ui_page_container_behavior.js"></script>
// 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.
/** @polymerBehavior */
const UiPageContainerBehaviorImpl = {
properties: {
/**
* ID for forward button label, which must be translated for display.
*
* Undefined if the visible page has no forward-navigation button.
*
* @type {string|undefined}
*/
forwardButtonTextId: String,
/**
* ID for backward button label, which must be translated for display.
*
* Undefined if the visible page has no backward-navigation button.
*
* @type {string|undefined}
*/
backwardButtonTextId: String,
/**
* ID for text of main UI Page heading.
*
* @type {string}
*/
headerId: String,
/**
* ID for text of main UI Page message body.
*
* @type {string}
*/
messageId: String,
/**
* Translated text to display on the forward-naviation button.
*
* Undefined if the visible page has no forward-navigation button.
*
* @type {string|undefined}
*/
forwardButtonText: {
type: String,
computed: 'computeLocalizedText_(forwardButtonTextId)',
},
/**
* Translated text to display on the backward-naviation button.
*
* Undefined if the visible page has no backward-navigation button.
*
* @type {string|undefined}
*/
backwardButtonText: {
type: String,
computed: 'computeLocalizedText_(backwardButtonTextId)',
},
/**
* Translated text of main UI Page heading.
*
* @type {string|undefined}
*/
headerText: {
type: String,
computed: 'computeLocalizedText_(headerId)',
},
/**
* Translated text of main UI Page heading. In general this can include
* some markup.
*
* @type {string|undefined}
*/
messageHtml: {
type: String,
computed: 'computeLocalizedText_(messageId)',
},
},
/**
* @param {string} textId Key for the localized string to appear on a
* button.
* @return {string|undefined} The localized string corresponding to the key
* textId. Return value is undefined if textId is not a key
* for any localized string. Note: this includes the case in which
* textId is undefined.
* @private
*/
computeLocalizedText_: function(textId) {
if (!this.i18nExists(textId))
return;
return this.i18nAdvanced(
textId, {attrs: {'id': (node, value) => node.tagName == 'A'}});
},
};
/** @polymerBehavior */
const UiPageContainerBehavior = [
I18nBehavior,
UiPageContainerBehaviorImpl,
];
......@@ -34,6 +34,15 @@ void AddMultiDeviceSetupStrings(content::WebUIDataSource* html_source) {
{"accept", IDS_MULTIDEVICE_SETUP_ACCEPT_LABEL},
{"cancel", IDS_CANCEL},
{"done", IDS_DONE},
{"setupFailedPageHeader", IDS_MULTIDEVICE_SETUP_SETUP_FAILED_PAGE_HEADER},
{"setupFailedPageMessage",
IDS_MULTIDEVICE_SETUP_SETUP_FAILED_PAGE_MESSAGE},
{"setupSucceededPageHeader",
IDS_MULTIDEVICE_SETUP_SETUP_SUCCEEDED_PAGE_HEADER},
{"setupSucceededPageMessage",
IDS_MULTIDEVICE_SETUP_SETUP_SUCCEEDED_PAGE_MESSAGE},
{"startSetupPageHeader", IDS_MULTIDEVICE_SETUP_START_SETUP_PAGE_HEADER},
{"startSetupPageMessage", IDS_MULTIDEVICE_SETUP_START_SETUP_PAGE_MESSAGE},
{"title", IDS_MULTIDEVICE_SETUP_DIALOG_TITLE},
{"tryAgain", IDS_MULTIDEVICE_SETUP_TRY_AGAIN_LABEL},
};
......
......@@ -7,66 +7,69 @@
* MultiDevice setup WebUI.
*/
cr.define('multidevice_setup', () => {
function registerTests() {
function registerIntegrationTests() {
suite('MultiDeviceSetup', () => {
/**
* MultiDeviceSetup created before each test.
* @type {MultiDeviceSetup}
* MultiDeviceSetup created before each test. Defined in setUp.
* @type {MultiDeviceSetup|undefined}
*/
let multiDeviceSetupElement;
/**
* Forward navigation button. Defined in setUp.
* @type {PaperButton|undefined}
*/
let forwardButton;
/**
* Backward navigation button. Defined in setUp.
* @type {PaperButton|undefined}
*/
let backwardButton;
const FAILURE = 'setup-failed-page';
const SUCCESS = 'setup-succeeded-page';
const START = 'start-setup-page';
function tapForwardNavigation() {
MockInteractions.tap(
multiDeviceSetupElement.$$('button-bar').$.forward);
}
function tapBackwardNavigation() {
MockInteractions.tap(
multiDeviceSetupElement.$$('button-bar').$.backward);
}
setup(() => {
PolymerTest.clearBody();
multiDeviceSetupElement = document.createElement('multidevice-setup');
document.body.appendChild(multiDeviceSetupElement);
forwardButton =
multiDeviceSetupElement.$$('button-bar /deep/ #forward');
backwardButton =
multiDeviceSetupElement.$$('button-bar /deep/ #backward');
});
test(
'Check SetupFailedPage forward button goes to start page',
done => {
multiDeviceSetupElement.visiblePageName_ = FAILURE;
multiDeviceSetupElement.addEventListener(
'visible-page_-changed', function() {
if (multiDeviceSetupElement.visiblePage_ &&
multiDeviceSetupElement.visiblePage_.is == START) {
done();
}
});
tapForwardNavigation();
});
test('Check SetupFailedPage backward button closes UI', done => {
test('SetupFailedPage forward button goes to start page', done => {
multiDeviceSetupElement.addEventListener(
'visible-page_-changed', function() {
if (multiDeviceSetupElement.$$('iron-pages > .iron-selected')
.is == START) {
done();
}
});
multiDeviceSetupElement.visiblePageName_ = FAILURE;
MockInteractions.tap(forwardButton);
});
test('SetupFailedPage backward button closes UI', done => {
multiDeviceSetupElement.addEventListener('ui-closed', () => done());
tapBackwardNavigation();
multiDeviceSetupElement.visiblePageName_ = FAILURE;
MockInteractions.tap(backwardButton);
});
test('Check SetupSucceededPage forward button closes UI', done => {
test('SetupSucceededPage forward button closes UI', done => {
multiDeviceSetupElement.visiblePageName_ = SUCCESS;
multiDeviceSetupElement.addEventListener('ui-closed', () => done());
tapForwardNavigation();
MockInteractions.tap(forwardButton);
});
test('Check StartSetupPage backward button closes UI', done => {
test('StartSetupPage backward button closes UI', done => {
multiDeviceSetupElement.visiblePageName_ = START;
multiDeviceSetupElement.addEventListener('ui-closed', () => done());
tapBackwardNavigation();
MockInteractions.tap(backwardButton);
});
});
}
return {registerTests: registerTests};
return {registerIntegrationTests: registerIntegrationTests};
});
......@@ -26,12 +26,18 @@ MultiDeviceSetupBrowserTest.prototype = {
browsePreload: 'chrome://multidevice-setup/',
extraLibraries: PolymerTest.getLibraries(ROOT_PATH).concat([
'navigation_test.js',
'integration_test.js',
'setup_succeeded_page_test.js',
]),
};
TEST_F('MultiDeviceSetupBrowserTest', 'All', function() {
multidevice_setup.registerTests();
TEST_F('MultiDeviceSetupBrowserTest', 'Integration', function() {
multidevice_setup.registerIntegrationTests();
mocha.run();
});
TEST_F('MultiDeviceSetupBrowserTest', 'SetupSucceededPage', function() {
multidevice_setup.registerSetupSucceededPageTests();
mocha.run();
});
......
// 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.
/**
* @fileoverview Suite of tests for button navigation functionality in
* MultiDevice setup WebUI.
*/
cr.define('multidevice_setup', () => {
function registerSetupSucceededPageTests() {
suite('MultiDeviceSetup', () => {
/**
* SetupSucceededPage created before each test. Defined in setUp.
* @type {SetupSucceededPage|undefined}
*/
let setupSucceededPageElement;
const SUCCESS = 'setup-succeeded-page';
setup(() => {
setupSucceededPageElement =
document.createElement('setup-succeeded-page');
document.body.appendChild(setupSucceededPageElement);
});
test('Settings link opens settings page', done => {
setupSucceededPageElement.addEventListener(
'settings-opened', () => done());
let settingsLink = setupSucceededPageElement.$$('#settings-link');
MockInteractions.tap(settingsLink);
});
});
}
return {registerSetupSucceededPageTests: registerSetupSucceededPageTests};
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment