mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-04-21 16:06:16 -04:00
Merge pull request #3161 from ether/feature/automatic_force_reconnect
Feature: automatic force reconnect
This commit is contained in:
commit
8081164a72
9 changed files with 301 additions and 14 deletions
|
@ -121,6 +121,10 @@
|
||||||
/* Privacy: disable IP logging */
|
/* Privacy: disable IP logging */
|
||||||
"disableIPlogging" : false,
|
"disableIPlogging" : false,
|
||||||
|
|
||||||
|
/* Time (in seconds) to automatically reconnect pad when a "Force reconnect"
|
||||||
|
message is shown to user. Set to 0 to disable automatic reconnection */
|
||||||
|
"automaticReconnectionTimeout" : 0,
|
||||||
|
|
||||||
/* Users for basic authentication. is_admin = true gives access to /admin.
|
/* Users for basic authentication. is_admin = true gives access to /admin.
|
||||||
If you do not uncomment this, /admin will not be available! */
|
If you do not uncomment this, /admin will not be available! */
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -74,6 +74,8 @@
|
||||||
"pad.modals.connected": "Connected.",
|
"pad.modals.connected": "Connected.",
|
||||||
"pad.modals.reconnecting": "Reconnecting to your pad..",
|
"pad.modals.reconnecting": "Reconnecting to your pad..",
|
||||||
"pad.modals.forcereconnect": "Force reconnect",
|
"pad.modals.forcereconnect": "Force reconnect",
|
||||||
|
"pad.modals.reconnecttimer": "Trying to reconnect in ",
|
||||||
|
"pad.modals.cancel": "Cancel",
|
||||||
|
|
||||||
"pad.modals.userdup": "Opened in another window",
|
"pad.modals.userdup": "Opened in another window",
|
||||||
"pad.modals.userdup.explanation": "This pad seems to be opened in more than one browser window on this computer.",
|
"pad.modals.userdup.explanation": "This pad seems to be opened in more than one browser window on this computer.",
|
||||||
|
|
|
@ -936,7 +936,7 @@ function handleSwitchToPad(client, message)
|
||||||
var currentSession = sessioninfos[client.id];
|
var currentSession = sessioninfos[client.id];
|
||||||
var padId = currentSession.padId;
|
var padId = currentSession.padId;
|
||||||
var roomClients = _getRoomClients(padId);
|
var roomClients = _getRoomClients(padId);
|
||||||
|
|
||||||
async.forEach(roomClients, function(client, callback) {
|
async.forEach(roomClients, function(client, callback) {
|
||||||
var sinfo = sessioninfos[client.id];
|
var sinfo = sessioninfos[client.id];
|
||||||
if(sinfo && sinfo.author == currentSession.author) {
|
if(sinfo && sinfo.author == currentSession.author) {
|
||||||
|
@ -1115,7 +1115,7 @@ function handleClientReady(client, message)
|
||||||
|
|
||||||
//Check if this author is already on the pad, if yes, kick the other sessions!
|
//Check if this author is already on the pad, if yes, kick the other sessions!
|
||||||
var roomClients = _getRoomClients(pad.id);
|
var roomClients = _getRoomClients(pad.id);
|
||||||
|
|
||||||
async.forEach(roomClients, function(client, callback) {
|
async.forEach(roomClients, function(client, callback) {
|
||||||
var sinfo = sessioninfos[client.id];
|
var sinfo = sessioninfos[client.id];
|
||||||
if(sinfo && sinfo.author == author) {
|
if(sinfo && sinfo.author == author) {
|
||||||
|
@ -1176,6 +1176,7 @@ function handleClientReady(client, message)
|
||||||
"accountPrivs": {
|
"accountPrivs": {
|
||||||
"maxRevisions": 100
|
"maxRevisions": 100
|
||||||
},
|
},
|
||||||
|
"automaticReconnectionTimeout": settings.automaticReconnectionTimeout,
|
||||||
"initialRevisionList": [],
|
"initialRevisionList": [],
|
||||||
"initialOptions": {
|
"initialOptions": {
|
||||||
"guestPolicy": "deny"
|
"guestPolicy": "deny"
|
||||||
|
@ -1676,13 +1677,13 @@ function composePadChangesets(padId, startNum, endNum, callback)
|
||||||
|
|
||||||
function _getRoomClients(padID) {
|
function _getRoomClients(padID) {
|
||||||
var roomClients = []; var room = socketio.sockets.adapter.rooms[padID];
|
var roomClients = []; var room = socketio.sockets.adapter.rooms[padID];
|
||||||
|
|
||||||
if (room) {
|
if (room) {
|
||||||
for (var id in room.sockets) {
|
for (var id in room.sockets) {
|
||||||
roomClients.push(socketio.sockets.sockets[id]);
|
roomClients.push(socketio.sockets.sockets[id]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return roomClients;
|
return roomClients;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -177,6 +177,11 @@ exports.loglevel = "INFO";
|
||||||
*/
|
*/
|
||||||
exports.disableIPlogging = false;
|
exports.disableIPlogging = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of seconds to automatically reconnect pad
|
||||||
|
*/
|
||||||
|
exports.automaticReconnectionTimeout = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disable Load Testing
|
* Disable Load Testing
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -517,6 +517,23 @@ table#otheruserstable {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* styles for the automatic reconnection timer: */
|
||||||
|
#connectivity .visible.with_reconnect_timer button,
|
||||||
|
#connectivity .visible.with_reconnect_timer .reconnecttimer * {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#connectivity .with_reconnect_timer .hidden,
|
||||||
|
#connectivity .with_reconnect_timer #defaulttext.hidden,
|
||||||
|
#connectivity .with_reconnect_timer button.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#connectivity .with_reconnect_timer #cancelreconnect {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
/* end of styles for the automatic reconnection timer */
|
||||||
|
|
||||||
#reconnect_form button {
|
#reconnect_form button {
|
||||||
font-size: 12pt;
|
font-size: 12pt;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
|
|
182
src/static/js/pad_automatic_reconnect.js
Normal file
182
src/static/js/pad_automatic_reconnect.js
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
|
||||||
|
exports.showCountDownTimerToReconnectOnModal = function($modal, pad) {
|
||||||
|
if (clientVars.automaticReconnectionTimeout && $modal.is('.with_reconnect_timer')) {
|
||||||
|
createCountDownElementsIfNecessary($modal);
|
||||||
|
|
||||||
|
var timer = createTimerForModal($modal, pad);
|
||||||
|
|
||||||
|
$modal.find('#cancelreconnect').one('click', function() {
|
||||||
|
timer.cancel();
|
||||||
|
disableAutomaticReconnection($modal);
|
||||||
|
});
|
||||||
|
|
||||||
|
enableAutomaticReconnection($modal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var createCountDownElementsIfNecessary = function($modal) {
|
||||||
|
var elementsDoNotExist = $modal.find('#cancelreconnect').length === 0;
|
||||||
|
if (elementsDoNotExist) {
|
||||||
|
var $defaultMessage = $modal.find('#defaulttext');
|
||||||
|
var $reconnectButton = $modal.find('#forcereconnect');
|
||||||
|
|
||||||
|
// create extra DOM elements, if they don't exist
|
||||||
|
var $reconnectTimerMessage = $('<p class="reconnecttimer"> \
|
||||||
|
<span data-l10n-id="pad.modals.reconnecttimer">Trying to reconnect in </span> \
|
||||||
|
<span class="timetoexpire"></span> \
|
||||||
|
</p>');
|
||||||
|
var $cancelReconnect = $('<button id="cancelreconnect" data-l10n-id="pad.modals.cancel">Cancel</button>');
|
||||||
|
|
||||||
|
localize($reconnectTimerMessage);
|
||||||
|
localize($cancelReconnect);
|
||||||
|
|
||||||
|
$reconnectTimerMessage.insertAfter($defaultMessage);
|
||||||
|
$cancelReconnect.insertAfter($reconnectButton);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var localize = function($element) {
|
||||||
|
html10n.translateElement(html10n.translations, $element.get(0));
|
||||||
|
};
|
||||||
|
|
||||||
|
var createTimerForModal = function($modal, pad) {
|
||||||
|
var timeUntilReconnection = clientVars.automaticReconnectionTimeout * reconnectionTries.nextTry();
|
||||||
|
var timer = new CountDownTimer(timeUntilReconnection);
|
||||||
|
|
||||||
|
timer.onTick(function(minutes, seconds) {
|
||||||
|
updateCountDownTimerMessage($modal, minutes, seconds);
|
||||||
|
}).onExpire(function() {
|
||||||
|
var wasANetworkError = $modal.is('.disconnected');
|
||||||
|
if (wasANetworkError) {
|
||||||
|
// cannot simply reconnect, client is having issues to establish connection to server
|
||||||
|
waitUntilClientCanConnectToServerAndThen(function() { forceReconnection($modal); }, pad);
|
||||||
|
} else {
|
||||||
|
forceReconnection($modal);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
return timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
var disableAutomaticReconnection = function($modal) {
|
||||||
|
toggleAutomaticReconnectionOption($modal, true);
|
||||||
|
}
|
||||||
|
var enableAutomaticReconnection = function($modal) {
|
||||||
|
toggleAutomaticReconnectionOption($modal, false);
|
||||||
|
}
|
||||||
|
var toggleAutomaticReconnectionOption = function($modal, disableAutomaticReconnect) {
|
||||||
|
$modal.find('#cancelreconnect, .reconnecttimer').toggleClass('hidden', disableAutomaticReconnect);
|
||||||
|
$modal.find('#defaulttext').toggleClass('hidden', !disableAutomaticReconnect);
|
||||||
|
}
|
||||||
|
|
||||||
|
var waitUntilClientCanConnectToServerAndThen = function(callback, pad) {
|
||||||
|
whenConnectionIsRestablishedWithServer(callback, pad);
|
||||||
|
pad.socket.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
var whenConnectionIsRestablishedWithServer = function(callback, pad) {
|
||||||
|
// only add listener for the first try, don't need to add another listener
|
||||||
|
// on every unsuccessful try
|
||||||
|
if (reconnectionTries.counter === 1) {
|
||||||
|
pad.socket.once('connect', callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var forceReconnection = function($modal) {
|
||||||
|
$modal.find('#forcereconnect').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
var updateCountDownTimerMessage = function($modal, minutes, seconds) {
|
||||||
|
minutes = minutes < 10 ? '0' + minutes : minutes;
|
||||||
|
seconds = seconds < 10 ? '0' + seconds : seconds;
|
||||||
|
|
||||||
|
$modal.find('.timetoexpire').text(minutes + ':' + seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
// store number of tries to reconnect to server, in order to increase time to wait
|
||||||
|
// until next try
|
||||||
|
var reconnectionTries = {
|
||||||
|
counter: 0,
|
||||||
|
|
||||||
|
nextTry: function() {
|
||||||
|
// double the time to try to reconnect on every time reconnection fails
|
||||||
|
var nextCounterFactor = Math.pow(2, this.counter);
|
||||||
|
this.counter++;
|
||||||
|
|
||||||
|
return nextCounterFactor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timer based on http://stackoverflow.com/a/20618517.
|
||||||
|
// duration: how many **seconds** until the timer ends
|
||||||
|
// granularity (optional): how many **milliseconds** between each 'tick' of timer. Default: 1000ms (1s)
|
||||||
|
var CountDownTimer = function(duration, granularity) {
|
||||||
|
this.duration = duration;
|
||||||
|
this.granularity = granularity || 1000;
|
||||||
|
this.running = false;
|
||||||
|
|
||||||
|
this.onTickCallbacks = [];
|
||||||
|
this.onExpireCallbacks = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
CountDownTimer.prototype.start = function() {
|
||||||
|
if (this.running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.running = true;
|
||||||
|
var start = Date.now(),
|
||||||
|
that = this,
|
||||||
|
diff;
|
||||||
|
|
||||||
|
(function timer() {
|
||||||
|
diff = that.duration - Math.floor((Date.now() - start) / 1000);
|
||||||
|
|
||||||
|
if (diff > 0) {
|
||||||
|
that.timeoutId = setTimeout(timer, that.granularity);
|
||||||
|
that.tick(diff);
|
||||||
|
} else {
|
||||||
|
that.running = false;
|
||||||
|
that.tick(0);
|
||||||
|
that.expire();
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
};
|
||||||
|
|
||||||
|
CountDownTimer.prototype.tick = function(diff) {
|
||||||
|
var obj = CountDownTimer.parse(diff);
|
||||||
|
this.onTickCallbacks.forEach(function(callback) {
|
||||||
|
callback.call(this, obj.minutes, obj.seconds);
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
CountDownTimer.prototype.expire = function() {
|
||||||
|
this.onExpireCallbacks.forEach(function(callback) {
|
||||||
|
callback.call(this);
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
CountDownTimer.prototype.onTick = function(callback) {
|
||||||
|
if (typeof callback === 'function') {
|
||||||
|
this.onTickCallbacks.push(callback);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
CountDownTimer.prototype.onExpire = function(callback) {
|
||||||
|
if (typeof callback === 'function') {
|
||||||
|
this.onExpireCallbacks.push(callback);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
CountDownTimer.prototype.cancel = function() {
|
||||||
|
this.running = false;
|
||||||
|
clearTimeout(this.timeoutId);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
CountDownTimer.parse = function(seconds) {
|
||||||
|
return {
|
||||||
|
'minutes': (seconds / 60) | 0,
|
||||||
|
'seconds': (seconds % 60) | 0
|
||||||
|
};
|
||||||
|
};
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
@ -19,8 +19,9 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var padeditbar = require('./pad_editbar').padeditbar;
|
var padeditbar = require('./pad_editbar').padeditbar;
|
||||||
|
var automaticReconnect = require('./pad_automatic_reconnect');
|
||||||
|
|
||||||
var padmodals = (function()
|
var padmodals = (function()
|
||||||
{
|
{
|
||||||
|
@ -35,6 +36,10 @@ var padmodals = (function()
|
||||||
padeditbar.toggleDropDown("none", function() {
|
padeditbar.toggleDropDown("none", function() {
|
||||||
$("#connectivity .visible").removeClass('visible');
|
$("#connectivity .visible").removeClass('visible');
|
||||||
$("#connectivity ."+messageId).addClass('visible');
|
$("#connectivity ."+messageId).addClass('visible');
|
||||||
|
|
||||||
|
var $modal = $('#connectivity .' + messageId);
|
||||||
|
automaticReconnect.showCountDownTimerToReconnectOnModal($modal, pad);
|
||||||
|
|
||||||
padeditbar.toggleDropDown("connectivity");
|
padeditbar.toggleDropDown("connectivity");
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -249,12 +249,12 @@
|
||||||
<div class="userdup">
|
<div class="userdup">
|
||||||
<h1 data-l10n-id="pad.modals.userdup"></h1>
|
<h1 data-l10n-id="pad.modals.userdup"></h1>
|
||||||
<h2 data-l10n-id="pad.modals.userdup.explanation"></h2>
|
<h2 data-l10n-id="pad.modals.userdup.explanation"></h2>
|
||||||
<p data-l10n-id="pad.modals.userdup.advice"></p>
|
<p id="defaulttext" data-l10n-id="pad.modals.userdup.advice"></p>
|
||||||
<button id="forcereconnect" data-l10n-id="pad.modals.forcereconnect"></button>
|
<button id="forcereconnect" data-l10n-id="pad.modals.forcereconnect"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="unauth">
|
<div class="unauth">
|
||||||
<h1 data-l10n-id="pad.modals.unauth"></h1>
|
<h1 data-l10n-id="pad.modals.unauth"></h1>
|
||||||
<p data-l10n-id="pad.modals.unauth.explanation"></p>
|
<p id="defaulttext" data-l10n-id="pad.modals.unauth.explanation"></p>
|
||||||
<button id="forcereconnect" data-l10n-id="pad.modals.forcereconnect"></button>
|
<button id="forcereconnect" data-l10n-id="pad.modals.forcereconnect"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="looping">
|
<div class="looping">
|
||||||
|
@ -267,16 +267,16 @@
|
||||||
<h2 data-l10n-id="pad.modals.initsocketfail.explanation"></h2>
|
<h2 data-l10n-id="pad.modals.initsocketfail.explanation"></h2>
|
||||||
<p data-l10n-id="pad.modals.initsocketfail.cause"></p>
|
<p data-l10n-id="pad.modals.initsocketfail.cause"></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="slowcommit">
|
<div class="slowcommit with_reconnect_timer">
|
||||||
<h1 data-l10n-id="pad.modals.disconnected"></h1>
|
<h1 data-l10n-id="pad.modals.disconnected"></h1>
|
||||||
<h2 data-l10n-id="pad.modals.slowcommit.explanation"></h2>
|
<h2 data-l10n-id="pad.modals.slowcommit.explanation"></h2>
|
||||||
<p data-l10n-id="pad.modals.slowcommit.cause"></p>
|
<p id="defaulttext" data-l10n-id="pad.modals.slowcommit.cause"></p>
|
||||||
<button id="forcereconnect" data-l10n-id="pad.modals.forcereconnect"></button>
|
<button id="forcereconnect" data-l10n-id="pad.modals.forcereconnect"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="badChangeset">
|
<div class="badChangeset with_reconnect_timer">
|
||||||
<h1 data-l10n-id="pad.modals.disconnected"></h1>
|
<h1 data-l10n-id="pad.modals.disconnected"></h1>
|
||||||
<h2 data-l10n-id="pad.modals.badChangeset.explanation"></h2>
|
<h2 data-l10n-id="pad.modals.badChangeset.explanation"></h2>
|
||||||
<p data-l10n-id="pad.modals.badChangeset.cause"></p>
|
<p id="defaulttext" data-l10n-id="pad.modals.badChangeset.cause"></p>
|
||||||
<button id="forcereconnect" data-l10n-id="pad.modals.forcereconnect"></button>
|
<button id="forcereconnect" data-l10n-id="pad.modals.forcereconnect"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="corruptPad">
|
<div class="corruptPad">
|
||||||
|
@ -288,11 +288,11 @@
|
||||||
<h1 data-l10n-id="pad.modals.deleted"></h1>
|
<h1 data-l10n-id="pad.modals.deleted"></h1>
|
||||||
<p data-l10n-id="pad.modals.deleted.explanation"></p>
|
<p data-l10n-id="pad.modals.deleted.explanation"></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="disconnected">
|
<div class="disconnected with_reconnect_timer">
|
||||||
<% e.begin_block("disconnected"); %>
|
<% e.begin_block("disconnected"); %>
|
||||||
<h1 data-l10n-id="pad.modals.disconnected"></h1>
|
<h1 data-l10n-id="pad.modals.disconnected"></h1>
|
||||||
<h2 data-l10n-id="pad.modals.disconnected.explanation"></h2>
|
<h2 data-l10n-id="pad.modals.disconnected.explanation"></h2>
|
||||||
<p data-l10n-id="pad.modals.disconnected.cause"></p>
|
<p id="defaulttext" data-l10n-id="pad.modals.disconnected.cause"></p>
|
||||||
<button id="forcereconnect" data-l10n-id="pad.modals.forcereconnect"></button>
|
<button id="forcereconnect" data-l10n-id="pad.modals.forcereconnect"></button>
|
||||||
<% e.end_block(); %>
|
<% e.end_block(); %>
|
||||||
</div>
|
</div>
|
||||||
|
|
71
tests/frontend/specs/automatic_reconnect.js
Normal file
71
tests/frontend/specs/automatic_reconnect.js
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
describe('Automatic pad reload on Force Reconnect message', function() {
|
||||||
|
var padId, $originalPadFrame;
|
||||||
|
|
||||||
|
beforeEach(function(done) {
|
||||||
|
padId = helper.newPad(function() {
|
||||||
|
// enable userdup error to have timer to force reconnect
|
||||||
|
var $errorMessageModal = helper.padChrome$('#connectivity .userdup');
|
||||||
|
$errorMessageModal.addClass('with_reconnect_timer');
|
||||||
|
|
||||||
|
// make sure there's a timeout set, otherwise automatic reconnect won't be enabled
|
||||||
|
helper.padChrome$.window.clientVars.automaticReconnectionTimeout = 2;
|
||||||
|
|
||||||
|
// open same pad on another iframe, to force userdup error
|
||||||
|
var $otherIframeWithSamePad = $('<iframe src="/p/' + padId + '" style="height: 1px;"></iframe>');
|
||||||
|
$originalPadFrame = $('#iframe-container iframe');
|
||||||
|
$otherIframeWithSamePad.insertAfter($originalPadFrame);
|
||||||
|
|
||||||
|
// wait for modal to be displayed
|
||||||
|
helper.waitFor(function() {
|
||||||
|
return $errorMessageModal.is(':visible');
|
||||||
|
}, 50000).done(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.timeout(60000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('displays a count down timer to automatically reconnect', function(done) {
|
||||||
|
var $errorMessageModal = helper.padChrome$('#connectivity .userdup');
|
||||||
|
var $countDownTimer = $errorMessageModal.find('.reconnecttimer');
|
||||||
|
|
||||||
|
expect($countDownTimer.is(':visible')).to.be(true);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
context('and user clicks on Cancel', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
var $errorMessageModal = helper.padChrome$('#connectivity .userdup');
|
||||||
|
$errorMessageModal.find('#cancelreconnect').click();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not show Cancel button nor timer anymore', function(done) {
|
||||||
|
var $errorMessageModal = helper.padChrome$('#connectivity .userdup');
|
||||||
|
var $countDownTimer = $errorMessageModal.find('.reconnecttimer');
|
||||||
|
var $cancelButton = $errorMessageModal.find('#cancelreconnect');
|
||||||
|
|
||||||
|
expect($countDownTimer.is(':visible')).to.be(false);
|
||||||
|
expect($cancelButton.is(':visible')).to.be(false);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
context('and user does not click on Cancel until timer expires', function() {
|
||||||
|
var padWasReloaded = false;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
$originalPadFrame.one('load', function() {
|
||||||
|
padWasReloaded = true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('reloads the pad', function(done) {
|
||||||
|
helper.waitFor(function() {
|
||||||
|
return padWasReloaded;
|
||||||
|
}, 5000).done(done);
|
||||||
|
|
||||||
|
this.timeout(5000);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Add table
Add a link
Reference in a new issue