Merge pull request #5074 from epixa/5061-import-firefox-bug

Safely window.confirm when importing saved object
This commit is contained in:
Lukas Olson 2015-10-12 14:36:55 -07:00
commit 95873a07c7
5 changed files with 122 additions and 7 deletions

View file

@ -55,6 +55,7 @@ exports.reload = function () {
'ui/persisted_log',
'ui/private',
'ui/promises',
'ui/safe_confirm',
'ui/state_management/app_state',
'ui/state_management/global_state',
'ui/storage',

View file

@ -4,6 +4,7 @@ define(function (require) {
require('ui/es');
require('ui/promises');
require('ui/safe_confirm');
require('ui/index_patterns');
require('ui/modules').get('kibana/courier')

View file

@ -1,5 +1,5 @@
define(function (require) {
return function SavedObjectFactory(es, kbnIndex, Promise, Private, Notifier, indexPatterns) {
return function SavedObjectFactory(es, kbnIndex, Promise, Private, Notifier, safeConfirm, indexPatterns) {
var angular = require('angular');
var errors = require('ui/errors');
var _ = require('lodash');
@ -252,12 +252,12 @@ define(function (require) {
if (_.get(err, 'origError.status') === 409) {
var confirmMessage = 'Are you sure you want to overwrite ' + self.title + '?';
if (window.confirm(confirmMessage)) { // eslint-disable-line no-alert
return docSource.doIndex(source).then(finish);
}
// if the user doesn't overwrite record, just swallow the error
return;
return safeConfirm(confirmMessage).then(
function () {
return docSource.doIndex(source).then(finish);
},
_.noop // if the user doesn't overwrite record, just swallow the error
);
}
return Promise.reject(err);
});

View file

@ -0,0 +1,82 @@
describe('ui/safe_confirm', function () {
var sinon = require('sinon');
var expect = require('expect.js');
var ngMock = require('ngMock');
var $rootScope;
var $window;
var $timeout;
var message;
var safeConfirm;
var promise;
beforeEach(function () {
ngMock.module('kibana', function ($provide) {
$provide.value('$window', {
confirm: sinon.stub().returns(true)
});
});
ngMock.inject(function ($injector) {
safeConfirm = $injector.get('safeConfirm');
$rootScope = $injector.get('$rootScope');
$window = $injector.get('$window');
$timeout = $injector.get('$timeout');
});
message = 'woah';
promise = safeConfirm(message);
});
context('before timeout completes', function () {
it('$window.confirm is not invoked', function () {
expect($window.confirm.called).to.be(false);
});
it('returned promise is not resolved', function () {
var isResolved = false;
function markAsResolved() {
isResolved = true;
}
promise.then(markAsResolved, markAsResolved);
$rootScope.$apply(); // attempt to resolve the promise, but this won't flush $timeout promises
expect(isResolved).to.be(false);
});
});
context('after timeout completes', function () {
it('$window.confirm is invoked with message', function () {
$timeout.flush();
expect($window.confirm.calledWith(message)).to.be(true);
});
context('when confirmed', function () {
it('promise is fulfilled with true', function () {
$timeout.flush();
var value;
promise.then(function (v) {
value = v;
});
$rootScope.$apply();
expect(value).to.be(true);
});
});
context('when canceled', function () {
it('promise is rejected with false', function () {
$window.confirm.returns(false); // must be set before $timeout.flush()
$timeout.flush();
var value;
promise.then(null, function (v) {
value = v;
});
$rootScope.$apply();
expect(value).to.be(false);
});
});
});
});

View file

@ -0,0 +1,31 @@
define(function (require) {
require('ui/modules').get('kibana')
/*
* Angular doesn't play well with thread blocking calls such as
* window.confirm() unless those calls are specifically handled inside a call
* to $timeout(). Rather than litter the code with that implementation
* detail, safeConfirm() can be used.
*
* WARNING: safeConfirm differs from a native call to window.confirm in that
* it only blocks the thread beginning on the next tick. For that reason, a
* promise is returned so consumers can handle the control flow.
*
* Usage:
* safeConfirm('This message will be passed to window.confirm()').then(
* function () {
* // user clicked confirm
* },
* function () {
* // user canceled the confirmation
* }
* );
*/
.factory('safeConfirm', function ($window, $timeout, $q) {
return function safeConfirm(message) {
return $timeout(function () {
return $window.confirm(message) || $q.reject(false);
});
};
});
});