mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1062126: Loop panel UI shouldn't be fully reset when reopened, r=mikedeboer.
This commit is contained in:
parent
00267b391a
commit
ce441a683d
@ -35,6 +35,7 @@
|
||||
<script type="text/javascript" src="loop/shared/js/utils.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/js/models.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/js/router.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/js/mixins.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/js/views.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/js/feedbackApiClient.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/js/websocket.js"></script>
|
||||
|
@ -11,10 +11,10 @@ var loop = loop || {};
|
||||
loop.panel = (function(_, mozL10n) {
|
||||
"use strict";
|
||||
|
||||
var sharedViews = loop.shared.views,
|
||||
sharedModels = loop.shared.models,
|
||||
// aliasing translation function as __ for concision
|
||||
__ = mozL10n.get;
|
||||
var sharedViews = loop.shared.views;
|
||||
var sharedModels = loop.shared.models;
|
||||
var sharedMixins = loop.shared.mixins;
|
||||
var __ = mozL10n.get; // aliasing translation function as __ for concision
|
||||
|
||||
/**
|
||||
* Panel router.
|
||||
@ -73,41 +73,11 @@ loop.panel = (function(_, mozL10n) {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Dropdown menu mixin.
|
||||
* @type {Object}
|
||||
*/
|
||||
var DropdownMenuMixin = {
|
||||
getInitialState: function() {
|
||||
return {showMenu: false};
|
||||
},
|
||||
|
||||
_onBodyClick: function() {
|
||||
this.setState({showMenu: false});
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
document.body.addEventListener("click", this._onBodyClick);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
document.body.removeEventListener("click", this._onBodyClick);
|
||||
},
|
||||
|
||||
showDropdownMenu: function() {
|
||||
this.setState({showMenu: true});
|
||||
},
|
||||
|
||||
hideDropdownMenu: function() {
|
||||
this.setState({showMenu: false});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Availability drop down menu subview.
|
||||
*/
|
||||
var AvailabilityDropdown = React.createClass({displayName: 'AvailabilityDropdown',
|
||||
mixins: [DropdownMenuMixin],
|
||||
mixins: [sharedMixins.DropdownMenuMixin],
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
@ -239,7 +209,7 @@ loop.panel = (function(_, mozL10n) {
|
||||
* Panel settings (gear) menu.
|
||||
*/
|
||||
var SettingsDropdown = React.createClass({displayName: 'SettingsDropdown',
|
||||
mixins: [DropdownMenuMixin],
|
||||
mixins: [sharedMixins.DropdownMenuMixin],
|
||||
|
||||
handleClickSettingsEntry: function() {
|
||||
// XXX to be implemented
|
||||
@ -308,7 +278,12 @@ loop.panel = (function(_, mozL10n) {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Call url result view.
|
||||
*/
|
||||
var CallUrlResult = React.createClass({displayName: 'CallUrlResult',
|
||||
mixins: [sharedMixins.DocumentVisibilityMixin],
|
||||
|
||||
propTypes: {
|
||||
callUrl: React.PropTypes.string,
|
||||
callUrlExpiry: React.PropTypes.number,
|
||||
@ -325,6 +300,14 @@ loop.panel = (function(_, mozL10n) {
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Provided by DocumentVisibilityMixin. Schedules retrieval of a new call
|
||||
* URL everytime the panel is reopened.
|
||||
*/
|
||||
onDocumentVisible: function() {
|
||||
this._fetchCallUrl();
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a random 5 character string used to identify
|
||||
* the conversation.
|
||||
@ -341,6 +324,13 @@ loop.panel = (function(_, mozL10n) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._fetchCallUrl();
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetches a call URL.
|
||||
*/
|
||||
_fetchCallUrl: function() {
|
||||
this.setState({pending: true});
|
||||
this.props.client.requestCallUrl(this.conversationIdentifier(),
|
||||
this._onCallUrlReceived);
|
||||
@ -506,7 +496,8 @@ loop.panel = (function(_, mozL10n) {
|
||||
__("display_name_guest");
|
||||
return (
|
||||
React.DOM.div(null,
|
||||
NotificationListView({notifications: this.props.notifications}),
|
||||
NotificationListView({notifications: this.props.notifications,
|
||||
clearOnDocumentHidden: true}),
|
||||
TabView({onSelect: this.selectTab},
|
||||
Tab({name: "call"},
|
||||
CallUrlResult({client: this.props.client,
|
||||
@ -547,42 +538,12 @@ loop.panel = (function(_, mozL10n) {
|
||||
if (!options.document) {
|
||||
throw new Error("missing required document");
|
||||
}
|
||||
this.document = options.document;
|
||||
|
||||
this._registerVisibilityChangeEvent();
|
||||
|
||||
this.on("panel:open", this.reset, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Register the DOM visibility API event for the whole document, and trigger
|
||||
* appropriate events accordingly:
|
||||
*
|
||||
* - `panel:opened` when the panel is open
|
||||
* - `panel:closed` when the panel is closed
|
||||
*
|
||||
* @link http://www.w3.org/TR/page-visibility/
|
||||
*/
|
||||
_registerVisibilityChangeEvent: function() {
|
||||
// XXX pass in the visibility status to detect when to generate a new
|
||||
// panel view
|
||||
this.document.addEventListener("visibilitychange", function(event) {
|
||||
this.trigger(event.currentTarget.hidden ? "panel:closed"
|
||||
: "panel:open");
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Default entry point.
|
||||
*/
|
||||
home: function() {
|
||||
this.reset();
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets this router to its initial state.
|
||||
*/
|
||||
reset: function() {
|
||||
this._notifications.reset();
|
||||
var client = new loop.Client({
|
||||
baseServerUrl: navigator.mozLoop.serverUrl
|
||||
|
@ -11,10 +11,10 @@ var loop = loop || {};
|
||||
loop.panel = (function(_, mozL10n) {
|
||||
"use strict";
|
||||
|
||||
var sharedViews = loop.shared.views,
|
||||
sharedModels = loop.shared.models,
|
||||
// aliasing translation function as __ for concision
|
||||
__ = mozL10n.get;
|
||||
var sharedViews = loop.shared.views;
|
||||
var sharedModels = loop.shared.models;
|
||||
var sharedMixins = loop.shared.mixins;
|
||||
var __ = mozL10n.get; // aliasing translation function as __ for concision
|
||||
|
||||
/**
|
||||
* Panel router.
|
||||
@ -73,41 +73,11 @@ loop.panel = (function(_, mozL10n) {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Dropdown menu mixin.
|
||||
* @type {Object}
|
||||
*/
|
||||
var DropdownMenuMixin = {
|
||||
getInitialState: function() {
|
||||
return {showMenu: false};
|
||||
},
|
||||
|
||||
_onBodyClick: function() {
|
||||
this.setState({showMenu: false});
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
document.body.addEventListener("click", this._onBodyClick);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
document.body.removeEventListener("click", this._onBodyClick);
|
||||
},
|
||||
|
||||
showDropdownMenu: function() {
|
||||
this.setState({showMenu: true});
|
||||
},
|
||||
|
||||
hideDropdownMenu: function() {
|
||||
this.setState({showMenu: false});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Availability drop down menu subview.
|
||||
*/
|
||||
var AvailabilityDropdown = React.createClass({
|
||||
mixins: [DropdownMenuMixin],
|
||||
mixins: [sharedMixins.DropdownMenuMixin],
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
@ -239,7 +209,7 @@ loop.panel = (function(_, mozL10n) {
|
||||
* Panel settings (gear) menu.
|
||||
*/
|
||||
var SettingsDropdown = React.createClass({
|
||||
mixins: [DropdownMenuMixin],
|
||||
mixins: [sharedMixins.DropdownMenuMixin],
|
||||
|
||||
handleClickSettingsEntry: function() {
|
||||
// XXX to be implemented
|
||||
@ -308,7 +278,12 @@ loop.panel = (function(_, mozL10n) {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Call url result view.
|
||||
*/
|
||||
var CallUrlResult = React.createClass({
|
||||
mixins: [sharedMixins.DocumentVisibilityMixin],
|
||||
|
||||
propTypes: {
|
||||
callUrl: React.PropTypes.string,
|
||||
callUrlExpiry: React.PropTypes.number,
|
||||
@ -325,6 +300,14 @@ loop.panel = (function(_, mozL10n) {
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Provided by DocumentVisibilityMixin. Schedules retrieval of a new call
|
||||
* URL everytime the panel is reopened.
|
||||
*/
|
||||
onDocumentVisible: function() {
|
||||
this._fetchCallUrl();
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a random 5 character string used to identify
|
||||
* the conversation.
|
||||
@ -341,6 +324,13 @@ loop.panel = (function(_, mozL10n) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._fetchCallUrl();
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetches a call URL.
|
||||
*/
|
||||
_fetchCallUrl: function() {
|
||||
this.setState({pending: true});
|
||||
this.props.client.requestCallUrl(this.conversationIdentifier(),
|
||||
this._onCallUrlReceived);
|
||||
@ -506,7 +496,8 @@ loop.panel = (function(_, mozL10n) {
|
||||
__("display_name_guest");
|
||||
return (
|
||||
<div>
|
||||
<NotificationListView notifications={this.props.notifications} />
|
||||
<NotificationListView notifications={this.props.notifications}
|
||||
clearOnDocumentHidden={true} />
|
||||
<TabView onSelect={this.selectTab}>
|
||||
<Tab name="call">
|
||||
<CallUrlResult client={this.props.client}
|
||||
@ -547,42 +538,12 @@ loop.panel = (function(_, mozL10n) {
|
||||
if (!options.document) {
|
||||
throw new Error("missing required document");
|
||||
}
|
||||
this.document = options.document;
|
||||
|
||||
this._registerVisibilityChangeEvent();
|
||||
|
||||
this.on("panel:open", this.reset, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Register the DOM visibility API event for the whole document, and trigger
|
||||
* appropriate events accordingly:
|
||||
*
|
||||
* - `panel:opened` when the panel is open
|
||||
* - `panel:closed` when the panel is closed
|
||||
*
|
||||
* @link http://www.w3.org/TR/page-visibility/
|
||||
*/
|
||||
_registerVisibilityChangeEvent: function() {
|
||||
// XXX pass in the visibility status to detect when to generate a new
|
||||
// panel view
|
||||
this.document.addEventListener("visibilitychange", function(event) {
|
||||
this.trigger(event.currentTarget.hidden ? "panel:closed"
|
||||
: "panel:open");
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Default entry point.
|
||||
*/
|
||||
home: function() {
|
||||
this.reset();
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets this router to its initial state.
|
||||
*/
|
||||
reset: function() {
|
||||
this._notifications.reset();
|
||||
var client = new loop.Client({
|
||||
baseServerUrl: navigator.mozLoop.serverUrl
|
||||
|
@ -12,8 +12,6 @@
|
||||
</head>
|
||||
<body class="panel" onload="loop.panel.init();">
|
||||
|
||||
<div id="messages"></div>
|
||||
|
||||
<div id="main"></div>
|
||||
|
||||
<script type="text/javascript" src="loop/shared/libs/react-0.11.1.js"></script>
|
||||
@ -25,6 +23,7 @@
|
||||
<script type="text/javascript" src="loop/shared/js/utils.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/js/models.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/js/router.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/js/mixins.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/js/views.js"></script>
|
||||
<script type="text/javascript" src="loop/js/client.js"></script>
|
||||
<script type="text/javascript" src="loop/js/desktopRouter.js"></script>
|
||||
|
@ -137,8 +137,12 @@
|
||||
|
||||
/* Specific cases */
|
||||
|
||||
.panel #messages .alert {
|
||||
margin-bottom: 0;
|
||||
.panel .messages {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.panel .messages .alert {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Dropdown menu (shared styles) */
|
||||
|
95
browser/components/loop/content/shared/js/mixins.js
Normal file
95
browser/components/loop/content/shared/js/mixins.js
Normal file
@ -0,0 +1,95 @@
|
||||
/* 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/. */
|
||||
|
||||
/* global loop:true */
|
||||
|
||||
var loop = loop || {};
|
||||
loop.shared = loop.shared || {};
|
||||
loop.shared.mixins = (function() {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Root object, by default set to window.
|
||||
* @type {DOMWindow|Object}
|
||||
*/
|
||||
var rootObject = window;
|
||||
|
||||
/**
|
||||
* Sets a new root object. This is useful for testing native DOM events so we
|
||||
* can fake them.
|
||||
*
|
||||
* @param {Object}
|
||||
*/
|
||||
function setRootObject(obj) {
|
||||
console.info("loop.shared.mixins: rootObject set to " + obj);
|
||||
rootObject = obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dropdown menu mixin.
|
||||
* @type {Object}
|
||||
*/
|
||||
var DropdownMenuMixin = {
|
||||
getInitialState: function() {
|
||||
return {showMenu: false};
|
||||
},
|
||||
|
||||
_onBodyClick: function() {
|
||||
this.setState({showMenu: false});
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
rootObject.document.body.addEventListener("click", this._onBodyClick);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
rootObject.document.body.removeEventListener("click", this._onBodyClick);
|
||||
},
|
||||
|
||||
showDropdownMenu: function() {
|
||||
this.setState({showMenu: true});
|
||||
},
|
||||
|
||||
hideDropdownMenu: function() {
|
||||
this.setState({showMenu: false});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Document visibility mixin. Allows defining the following hooks for when the
|
||||
* document visibility status changes:
|
||||
*
|
||||
* - {Function} onDocumentVisible For when the document becomes visible.
|
||||
* - {Function} onDocumentHidden For when the document becomes hidden.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
var DocumentVisibilityMixin = {
|
||||
_onDocumentVisibilityChanged: function(event) {
|
||||
var hidden = event.target.hidden;
|
||||
if (hidden && typeof this.onDocumentHidden === "function") {
|
||||
this.onDocumentHidden();
|
||||
}
|
||||
if (!hidden && typeof this.onDocumentVisible === "function") {
|
||||
this.onDocumentVisible();
|
||||
}
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
rootObject.document.addEventListener(
|
||||
"visibilitychange", this._onDocumentVisibilityChanged);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
rootObject.document.removeEventListener(
|
||||
"visibilitychange", this._onDocumentVisibilityChanged);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
setRootObject: setRootObject,
|
||||
DropdownMenuMixin: DropdownMenuMixin,
|
||||
DocumentVisibilityMixin: DocumentVisibilityMixin
|
||||
};
|
||||
})();
|
@ -12,6 +12,8 @@ loop.shared.views = (function(_, OT, l10n) {
|
||||
"use strict";
|
||||
|
||||
var sharedModels = loop.shared.models;
|
||||
var sharedMixins = loop.shared.mixins;
|
||||
|
||||
var WINDOW_AUTOCLOSE_TIMEOUT_IN_SECONDS = 5;
|
||||
|
||||
/**
|
||||
@ -575,8 +577,7 @@ loop.shared.views = (function(_, OT, l10n) {
|
||||
/**
|
||||
* Notification view.
|
||||
*/
|
||||
var NotificationView = React.createClass({
|
||||
displayName: 'NotificationView',
|
||||
var NotificationView = React.createClass({displayName: 'NotificationView',
|
||||
mixins: [Backbone.Events],
|
||||
|
||||
propTypes: {
|
||||
@ -599,10 +600,15 @@ loop.shared.views = (function(_, OT, l10n) {
|
||||
* Notification list view.
|
||||
*/
|
||||
var NotificationListView = React.createClass({displayName: 'NotificationListView',
|
||||
mixins: [Backbone.Events],
|
||||
mixins: [Backbone.Events, sharedMixins.DocumentVisibilityMixin],
|
||||
|
||||
propTypes: {
|
||||
notifications: React.PropTypes.object.isRequired
|
||||
notifications: React.PropTypes.object.isRequired,
|
||||
clearOnDocumentHidden: React.PropTypes.bool
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {clearOnDocumentHidden: false};
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
@ -615,9 +621,25 @@ loop.shared.views = (function(_, OT, l10n) {
|
||||
this.stopListening(this.props.notifications);
|
||||
},
|
||||
|
||||
/**
|
||||
* Provided by DocumentVisibilityMixin. Clears notifications stack when the
|
||||
* current document is hidden if the clearOnDocumentHidden prop is set to
|
||||
* true and the collection isn't empty.
|
||||
*/
|
||||
onDocumentHidden: function() {
|
||||
if (this.props.clearOnDocumentHidden &&
|
||||
this.props.notifications.length > 0) {
|
||||
// Note: The `silent` option prevents the `reset` event to be triggered
|
||||
// here, preventing the UI to "jump" a little because of the event
|
||||
// callback being processed in another tick (I think).
|
||||
this.props.notifications.reset([], {silent: true});
|
||||
this.forceUpdate();
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
React.DOM.div({id: "messages"},
|
||||
React.DOM.div({className: "messages"},
|
||||
this.props.notifications.map(function(notification, key) {
|
||||
return NotificationView({key: key, notification: notification});
|
||||
})
|
||||
|
@ -12,6 +12,8 @@ loop.shared.views = (function(_, OT, l10n) {
|
||||
"use strict";
|
||||
|
||||
var sharedModels = loop.shared.models;
|
||||
var sharedMixins = loop.shared.mixins;
|
||||
|
||||
var WINDOW_AUTOCLOSE_TIMEOUT_IN_SECONDS = 5;
|
||||
|
||||
/**
|
||||
@ -576,7 +578,6 @@ loop.shared.views = (function(_, OT, l10n) {
|
||||
* Notification view.
|
||||
*/
|
||||
var NotificationView = React.createClass({
|
||||
displayName: 'NotificationView',
|
||||
mixins: [Backbone.Events],
|
||||
|
||||
propTypes: {
|
||||
@ -599,10 +600,15 @@ loop.shared.views = (function(_, OT, l10n) {
|
||||
* Notification list view.
|
||||
*/
|
||||
var NotificationListView = React.createClass({
|
||||
mixins: [Backbone.Events],
|
||||
mixins: [Backbone.Events, sharedMixins.DocumentVisibilityMixin],
|
||||
|
||||
propTypes: {
|
||||
notifications: React.PropTypes.object.isRequired
|
||||
notifications: React.PropTypes.object.isRequired,
|
||||
clearOnDocumentHidden: React.PropTypes.bool
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {clearOnDocumentHidden: false};
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
@ -615,9 +621,25 @@ loop.shared.views = (function(_, OT, l10n) {
|
||||
this.stopListening(this.props.notifications);
|
||||
},
|
||||
|
||||
/**
|
||||
* Provided by DocumentVisibilityMixin. Clears notifications stack when the
|
||||
* current document is hidden if the clearOnDocumentHidden prop is set to
|
||||
* true and the collection isn't empty.
|
||||
*/
|
||||
onDocumentHidden: function() {
|
||||
if (this.props.clearOnDocumentHidden &&
|
||||
this.props.notifications.length > 0) {
|
||||
// Note: The `silent` option prevents the `reset` event to be triggered
|
||||
// here, preventing the UI to "jump" a little because of the event
|
||||
// callback being processed in another tick (I think).
|
||||
this.props.notifications.reset([], {silent: true});
|
||||
this.forceUpdate();
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div id="messages">{
|
||||
<div className="messages">{
|
||||
this.props.notifications.map(function(notification, key) {
|
||||
return <NotificationView key={key} notification={notification}/>;
|
||||
})
|
||||
|
@ -51,6 +51,7 @@ browser.jar:
|
||||
content/browser/loop/shared/js/feedbackApiClient.js (content/shared/js/feedbackApiClient.js)
|
||||
content/browser/loop/shared/js/models.js (content/shared/js/models.js)
|
||||
content/browser/loop/shared/js/router.js (content/shared/js/router.js)
|
||||
content/browser/loop/shared/js/mixins.js (content/shared/js/mixins.js)
|
||||
content/browser/loop/shared/js/views.js (content/shared/js/views.js)
|
||||
content/browser/loop/shared/js/utils.js (content/shared/js/utils.js)
|
||||
content/browser/loop/shared/js/websocket.js (content/shared/js/websocket.js)
|
||||
|
@ -36,6 +36,7 @@
|
||||
<script type="text/javascript" src="config.js"></script>
|
||||
<script type="text/javascript" src="shared/js/utils.js"></script>
|
||||
<script type="text/javascript" src="shared/js/models.js"></script>
|
||||
<script type="text/javascript" src="shared/js/mixins.js"></script>
|
||||
<script type="text/javascript" src="shared/js/views.js"></script>
|
||||
<script type="text/javascript" src="shared/js/router.js"></script>
|
||||
<script type="text/javascript" src="shared/js/websocket.js"></script>
|
||||
|
@ -36,6 +36,7 @@
|
||||
<script src="../../content/shared/js/feedbackApiClient.js"></script>
|
||||
<script src="../../content/shared/js/models.js"></script>
|
||||
<script src="../../content/shared/js/router.js"></script>
|
||||
<script src="../../content/shared/js/mixins.js"></script>
|
||||
<script src="../../content/shared/js/views.js"></script>
|
||||
<script src="../../content/shared/js/websocket.js"></script>
|
||||
<script src="../../content/js/client.js"></script>
|
||||
|
@ -2,6 +2,7 @@
|
||||
* 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/. */
|
||||
|
||||
/*jshint newcap:false*/
|
||||
/*global loop, sinon */
|
||||
|
||||
var expect = chai.expect;
|
||||
@ -82,25 +83,18 @@ describe("loop.panel", function() {
|
||||
});
|
||||
|
||||
describe("#home", function() {
|
||||
it("should reset the PanelView", function() {
|
||||
sandbox.stub(router, "reset");
|
||||
|
||||
router.home();
|
||||
|
||||
sinon.assert.calledOnce(router.reset);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#reset", function() {
|
||||
it("should clear all pending notifications", function() {
|
||||
beforeEach(function() {
|
||||
sandbox.stub(notifications, "reset");
|
||||
router.reset();
|
||||
});
|
||||
|
||||
it("should clear all pending notifications", function() {
|
||||
router.home();
|
||||
|
||||
sinon.assert.calledOnce(notifications.reset);
|
||||
});
|
||||
|
||||
it("should load the home view", function() {
|
||||
router.reset();
|
||||
router.home();
|
||||
|
||||
sinon.assert.calledOnce(router.loadReactComponent);
|
||||
sinon.assert.calledWithExactly(router.loadReactComponent,
|
||||
@ -111,51 +105,6 @@ describe("loop.panel", function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Events", function() {
|
||||
beforeEach(function() {
|
||||
sandbox.stub(loop.panel.PanelRouter.prototype, "trigger");
|
||||
});
|
||||
|
||||
it("should listen to document visibility changes", function() {
|
||||
var fakeDocument = {
|
||||
hidden: true,
|
||||
addEventListener: sandbox.spy()
|
||||
};
|
||||
|
||||
var router = createTestRouter(fakeDocument);
|
||||
|
||||
sinon.assert.calledOnce(fakeDocument.addEventListener);
|
||||
sinon.assert.calledWith(fakeDocument.addEventListener,
|
||||
"visibilitychange");
|
||||
});
|
||||
|
||||
it("should trigger panel:open when the panel document is visible",
|
||||
function() {
|
||||
var router = createTestRouter({
|
||||
hidden: false,
|
||||
addEventListener: function(name, cb) {
|
||||
cb({currentTarget: {hidden: false}});
|
||||
}
|
||||
});
|
||||
|
||||
sinon.assert.calledOnce(router.trigger);
|
||||
sinon.assert.calledWith(router.trigger, "panel:open");
|
||||
});
|
||||
|
||||
it("should trigger panel:closed when the panel document is hidden",
|
||||
function() {
|
||||
var router = createTestRouter({
|
||||
hidden: true,
|
||||
addEventListener: function(name, cb) {
|
||||
cb({currentTarget: {hidden: true}});
|
||||
}
|
||||
});
|
||||
|
||||
sinon.assert.calledOnce(router.trigger);
|
||||
sinon.assert.calledWith(router.trigger, "panel:closed");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("loop.panel.AvailabilityDropdown", function() {
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
<!-- App scripts -->
|
||||
<script src="../../content/shared/js/models.js"></script>
|
||||
<script src="../../content/shared/js/mixins.js"></script>
|
||||
<script src="../../content/shared/js/views.js"></script>
|
||||
<script src="../../content/shared/js/router.js"></script>
|
||||
<script src="../../content/shared/js/websocket.js"></script>
|
||||
@ -41,6 +42,7 @@
|
||||
|
||||
<!-- Test scripts -->
|
||||
<script src="models_test.js"></script>
|
||||
<script src="mixins_test.js"></script>
|
||||
<script src="views_test.js"></script>
|
||||
<script src="router_test.js"></script>
|
||||
<script src="websocket_test.js"></script>
|
||||
|
70
browser/components/loop/test/shared/mixins_test.js
Normal file
70
browser/components/loop/test/shared/mixins_test.js
Normal file
@ -0,0 +1,70 @@
|
||||
/* 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/. */
|
||||
|
||||
/* global loop, sinon */
|
||||
/* jshint newcap:false */
|
||||
|
||||
var expect = chai.expect;
|
||||
|
||||
describe("loop.shared.mixins", function() {
|
||||
"use strict";
|
||||
|
||||
var sandbox;
|
||||
var sharedMixins = loop.shared.mixins;
|
||||
|
||||
beforeEach(function() {
|
||||
sandbox = sinon.sandbox.create();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
describe("loop.panel.DocumentVisibilityMixin", function() {
|
||||
var comp, TestComp, onDocumentVisibleStub, onDocumentHiddenStub;
|
||||
|
||||
beforeEach(function() {
|
||||
onDocumentVisibleStub = sandbox.stub();
|
||||
onDocumentHiddenStub = sandbox.stub();
|
||||
|
||||
TestComp = React.createClass({
|
||||
mixins: [loop.shared.mixins.DocumentVisibilityMixin],
|
||||
onDocumentHidden: onDocumentHiddenStub,
|
||||
onDocumentVisible: onDocumentVisibleStub,
|
||||
render: function() {
|
||||
return React.DOM.div();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function setupFakeVisibilityEventDispatcher(event) {
|
||||
loop.shared.mixins.setRootObject({
|
||||
document: {
|
||||
addEventListener: function(_, fn) {
|
||||
fn(event);
|
||||
},
|
||||
removeEventListener: sandbox.stub()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
it("should call onDocumentVisible when document visibility changes to visible",
|
||||
function() {
|
||||
setupFakeVisibilityEventDispatcher({target: {hidden: false}});
|
||||
|
||||
comp = TestUtils.renderIntoDocument(TestComp());
|
||||
|
||||
sinon.assert.calledOnce(onDocumentVisibleStub);
|
||||
});
|
||||
|
||||
it("should call onDocumentVisible when document visibility changes to hidden",
|
||||
function() {
|
||||
setupFakeVisibilityEventDispatcher({target: {hidden: true}});
|
||||
|
||||
comp = TestUtils.renderIntoDocument(TestComp());
|
||||
|
||||
sinon.assert.calledOnce(onDocumentHiddenStub);
|
||||
});
|
||||
});
|
||||
});
|
@ -33,6 +33,7 @@
|
||||
<!-- App scripts -->
|
||||
<script src="../../content/shared/js/utils.js"></script>
|
||||
<script src="../../content/shared/js/models.js"></script>
|
||||
<script src="../../content/shared/js/mixins.js"></script>
|
||||
<script src="../../content/shared/js/views.js"></script>
|
||||
<script src="../../content/shared/js/router.js"></script>
|
||||
<script src="../../content/shared/js/websocket.js"></script>
|
||||
|
@ -34,6 +34,7 @@
|
||||
<script src="../content/shared/js/utils.js"></script>
|
||||
<script src="../content/shared/js/models.js"></script>
|
||||
<script src="../content/shared/js/router.js"></script>
|
||||
<script src="../content/shared/js/mixins.js"></script>
|
||||
<script src="../content/shared/js/views.js"></script>
|
||||
<script src="../content/js/client.js"></script>
|
||||
<script src="../content/js/desktopRouter.js"></script>
|
||||
|
Loading…
Reference in New Issue
Block a user