server/core/js/tests/specs/coreSpec.js

1021 lines
32 KiB
JavaScript
Raw Normal View History

/**
* ownCloud
*
* @author Vincent Petry
* @copyright 2014 Vincent Petry <pvince81@owncloud.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
describe('Core base tests', function() {
afterEach(function() {
// many tests call window.initCore so need to unregister global events
// ideally in the future we'll need a window.unloadCore() function
$(document).off('ajaxError.main');
$(document).off('unload.main');
$(document).off('beforeunload.main');
OC._userIsNavigatingAway = false;
OC._reloadCalled = false;
});
describe('Base values', function() {
it('Sets webroots', function() {
expect(OC.webroot).toBeDefined();
expect(OC.appswebroots).toBeDefined();
});
});
describe('basename', function() {
it('Returns the nothing if no file name given', function() {
expect(OC.basename('')).toEqual('');
});
it('Returns the nothing if dir is root', function() {
expect(OC.basename('/')).toEqual('');
});
it('Returns the same name if no path given', function() {
expect(OC.basename('some name.txt')).toEqual('some name.txt');
});
it('Returns the base name if root path given', function() {
expect(OC.basename('/some name.txt')).toEqual('some name.txt');
});
it('Returns the base name if double root path given', function() {
expect(OC.basename('//some name.txt')).toEqual('some name.txt');
});
it('Returns the base name if subdir given without root', function() {
expect(OC.basename('subdir/some name.txt')).toEqual('some name.txt');
});
it('Returns the base name if subdir given with root', function() {
expect(OC.basename('/subdir/some name.txt')).toEqual('some name.txt');
});
it('Returns the base name if subdir given with double root', function() {
expect(OC.basename('//subdir/some name.txt')).toEqual('some name.txt');
});
it('Returns the base name if subdir has dot', function() {
expect(OC.basename('/subdir.dat/some name.txt')).toEqual('some name.txt');
});
it('Returns dot if file name is dot', function() {
expect(OC.basename('/subdir/.')).toEqual('.');
});
// TODO: fix the source to make it work like PHP's basename
it('Returns the dir itself if no file name given', function() {
// TODO: fix the source to make it work like PHP's dirname
// expect(OC.basename('subdir/')).toEqual('subdir');
expect(OC.basename('subdir/')).toEqual('');
});
it('Returns the dir itself if no file name given with root', function() {
// TODO: fix the source to make it work like PHP's dirname
// expect(OC.basename('/subdir/')).toEqual('subdir');
expect(OC.basename('/subdir/')).toEqual('');
});
});
describe('dirname', function() {
it('Returns the nothing if no file name given', function() {
expect(OC.dirname('')).toEqual('');
});
it('Returns the root if dir is root', function() {
// TODO: fix the source to make it work like PHP's dirname
// expect(OC.dirname('/')).toEqual('/');
expect(OC.dirname('/')).toEqual('');
});
it('Returns the root if dir is double root', function() {
// TODO: fix the source to make it work like PHP's dirname
// expect(OC.dirname('//')).toEqual('/');
expect(OC.dirname('//')).toEqual('/'); // oh no...
});
it('Returns dot if dir is dot', function() {
expect(OC.dirname('.')).toEqual('.');
});
it('Returns dot if no root given', function() {
// TODO: fix the source to make it work like PHP's dirname
// expect(OC.dirname('some dir')).toEqual('.');
expect(OC.dirname('some dir')).toEqual('some dir'); // oh no...
});
it('Returns the dir name if file name and root path given', function() {
// TODO: fix the source to make it work like PHP's dirname
// expect(OC.dirname('/some name.txt')).toEqual('/');
expect(OC.dirname('/some name.txt')).toEqual('');
});
it('Returns the dir name if double root path given', function() {
expect(OC.dirname('//some name.txt')).toEqual('/'); // how lucky...
});
it('Returns the dir name if subdir given without root', function() {
expect(OC.dirname('subdir/some name.txt')).toEqual('subdir');
});
it('Returns the dir name if subdir given with root', function() {
expect(OC.dirname('/subdir/some name.txt')).toEqual('/subdir');
});
it('Returns the dir name if subdir given with double root', function() {
// TODO: fix the source to make it work like PHP's dirname
// expect(OC.dirname('//subdir/some name.txt')).toEqual('/subdir');
expect(OC.dirname('//subdir/some name.txt')).toEqual('//subdir'); // oh...
});
it('Returns the dir name if subdir has dot', function() {
expect(OC.dirname('/subdir.dat/some name.txt')).toEqual('/subdir.dat');
});
it('Returns the dir name if file name is dot', function() {
expect(OC.dirname('/subdir/.')).toEqual('/subdir');
});
it('Returns the dir name if no file name given', function() {
expect(OC.dirname('subdir/')).toEqual('subdir');
});
it('Returns the dir name if no file name given with root', function() {
expect(OC.dirname('/subdir/')).toEqual('/subdir');
});
});
2014-05-28 20:14:05 +00:00
describe('escapeHTML', function() {
it('Returns nothing if no string was given', function() {
expect(escapeHTML('')).toEqual('');
});
it('Returns a sanitized string if a string containing HTML is given', function() {
expect(escapeHTML('There needs to be a <script>alert(\"Unit\" + \'test\')</script> for it!')).toEqual('There needs to be a &lt;script&gt;alert(&quot;Unit&quot; + &#039;test&#039;)&lt;/script&gt; for it!');
});
2014-05-31 19:11:29 +00:00
it('Returns the string without modification if no potentially dangerous character is passed.', function() {
2014-05-28 20:14:05 +00:00
expect(escapeHTML('This is a good string without HTML.')).toEqual('This is a good string without HTML.');
});
});
describe('joinPaths', function() {
it('returns empty string with no or empty arguments', function() {
expect(OC.joinPaths()).toEqual('');
expect(OC.joinPaths('')).toEqual('');
expect(OC.joinPaths('', '')).toEqual('');
});
it('returns joined path sections', function() {
expect(OC.joinPaths('abc')).toEqual('abc');
expect(OC.joinPaths('abc', 'def')).toEqual('abc/def');
expect(OC.joinPaths('abc', 'def', 'ghi')).toEqual('abc/def/ghi');
});
it('keeps leading slashes', function() {
expect(OC.joinPaths('/abc')).toEqual('/abc');
expect(OC.joinPaths('/abc', '')).toEqual('/abc');
expect(OC.joinPaths('', '/abc')).toEqual('/abc');
expect(OC.joinPaths('/abc', 'def')).toEqual('/abc/def');
expect(OC.joinPaths('/abc', 'def', 'ghi')).toEqual('/abc/def/ghi');
});
it('keeps trailing slashes', function() {
expect(OC.joinPaths('', 'abc/')).toEqual('abc/');
expect(OC.joinPaths('abc/')).toEqual('abc/');
expect(OC.joinPaths('abc/', '')).toEqual('abc/');
expect(OC.joinPaths('abc', 'def/')).toEqual('abc/def/');
expect(OC.joinPaths('abc', 'def', 'ghi/')).toEqual('abc/def/ghi/');
});
it('splits paths in specified strings and discards extra slashes', function() {
expect(OC.joinPaths('//abc//')).toEqual('/abc/');
expect(OC.joinPaths('//abc//def//')).toEqual('/abc/def/');
expect(OC.joinPaths('//abc//', '//def//')).toEqual('/abc/def/');
expect(OC.joinPaths('//abc//', '//def//', '//ghi//')).toEqual('/abc/def/ghi/');
expect(OC.joinPaths('//abc//def//', '//ghi//jkl/mno/', '//pqr//'))
.toEqual('/abc/def/ghi/jkl/mno/pqr/');
2015-07-10 13:31:58 +00:00
expect(OC.joinPaths('/abc', '/def')).toEqual('/abc/def');
expect(OC.joinPaths('/abc/', '/def')).toEqual('/abc/def');
expect(OC.joinPaths('/abc/', 'def')).toEqual('/abc/def');
});
it('discards empty sections', function() {
expect(OC.joinPaths('abc', '', 'def')).toEqual('abc/def');
});
it('returns root if only slashes', function() {
expect(OC.joinPaths('//')).toEqual('/');
expect(OC.joinPaths('/', '/')).toEqual('/');
expect(OC.joinPaths('/', '//', '/')).toEqual('/');
});
});
2014-09-09 10:05:19 +00:00
describe('filePath', function() {
2014-09-09 11:08:50 +00:00
beforeEach(function() {
2014-09-09 10:05:19 +00:00
OC.webroot = 'http://localhost';
OC.appswebroots['files'] = OC.webroot + '/apps3/files';
2014-09-09 11:08:50 +00:00
});
afterEach(function() {
delete OC.appswebroots['files'];
});
2014-09-09 10:05:19 +00:00
2014-09-09 11:08:50 +00:00
it('Uses a direct link for css and images,' , function() {
2014-09-09 10:05:19 +00:00
expect(OC.filePath('core', 'css', 'style.css')).toEqual('http://localhost/core/css/style.css');
expect(OC.filePath('files', 'css', 'style.css')).toEqual('http://localhost/apps3/files/css/style.css');
expect(OC.filePath('core', 'img', 'image.png')).toEqual('http://localhost/core/img/image.png');
expect(OC.filePath('files', 'img', 'image.png')).toEqual('http://localhost/apps3/files/img/image.png');
});
it('Routes PHP files via index.php,' , function() {
expect(OC.filePath('core', 'ajax', 'test.php')).toEqual('http://localhost/index.php/core/ajax/test.php');
expect(OC.filePath('files', 'ajax', 'test.php')).toEqual('http://localhost/index.php/apps/files/ajax/test.php');
});
});
describe('Link functions', function() {
var TESTAPP = 'testapp';
var TESTAPP_ROOT = OC.webroot + '/appsx/testapp';
beforeEach(function() {
OC.appswebroots[TESTAPP] = TESTAPP_ROOT;
});
afterEach(function() {
// restore original array
delete OC.appswebroots[TESTAPP];
});
it('Generates correct links for core apps', function() {
expect(OC.linkTo('core', 'somefile.php')).toEqual(OC.webroot + '/core/somefile.php');
expect(OC.linkTo('admin', 'somefile.php')).toEqual(OC.webroot + '/admin/somefile.php');
});
it('Generates correct links for regular apps', function() {
expect(OC.linkTo(TESTAPP, 'somefile.php')).toEqual(OC.webroot + '/index.php/apps/' + TESTAPP + '/somefile.php');
});
it('Generates correct remote links', function() {
expect(OC.linkToRemote('webdav')).toEqual(window.location.protocol + '//' + window.location.host + OC.webroot + '/remote.php/webdav');
});
describe('Images', function() {
it('Generates image path with given extension', function() {
var svgSupportStub = sinon.stub(OC.Util, 'hasSVGSupport', function() { return true; });
expect(OC.imagePath('core', 'somefile.jpg')).toEqual(OC.webroot + '/core/img/somefile.jpg');
expect(OC.imagePath(TESTAPP, 'somefile.jpg')).toEqual(TESTAPP_ROOT + '/img/somefile.jpg');
svgSupportStub.restore();
});
it('Generates image path with svg extension when svg support exists', function() {
var svgSupportStub = sinon.stub(OC.Util, 'hasSVGSupport', function() { return true; });
expect(OC.imagePath('core', 'somefile')).toEqual(OC.webroot + '/core/img/somefile.svg');
expect(OC.imagePath(TESTAPP, 'somefile')).toEqual(TESTAPP_ROOT + '/img/somefile.svg');
svgSupportStub.restore();
});
it('Generates image path with png ext when svg support is not available', function() {
var svgSupportStub = sinon.stub(OC.Util, 'hasSVGSupport', function() { return false; });
expect(OC.imagePath('core', 'somefile')).toEqual(OC.webroot + '/core/img/somefile.png');
expect(OC.imagePath(TESTAPP, 'somefile')).toEqual(TESTAPP_ROOT + '/img/somefile.png');
svgSupportStub.restore();
});
});
});
describe('Query string building', function() {
it('Returns empty string when empty params', function() {
expect(OC.buildQueryString()).toEqual('');
expect(OC.buildQueryString({})).toEqual('');
});
it('Encodes regular query strings', function() {
expect(OC.buildQueryString({
a: 'abc',
b: 'def'
})).toEqual('a=abc&b=def');
});
it('Encodes special characters', function() {
expect(OC.buildQueryString({
2014-03-05 00:10:39 +00:00
unicode: '汉字'
})).toEqual('unicode=%E6%B1%89%E5%AD%97');
expect(OC.buildQueryString({
2014-03-01 01:46:27 +00:00
b: 'spaace value',
'space key': 'normalvalue',
'slash/this': 'amp&ersand'
})).toEqual('b=spaace%20value&space%20key=normalvalue&slash%2Fthis=amp%26ersand');
});
it('Encodes data types and empty values', function() {
expect(OC.buildQueryString({
'keywithemptystring': '',
2014-03-01 01:46:27 +00:00
'keywithnull': null,
'keywithundefined': null,
something: 'else'
})).toEqual('keywithemptystring=&keywithnull&keywithundefined&something=else');
expect(OC.buildQueryString({
2014-03-01 01:46:27 +00:00
'booleanfalse': false,
'booleantrue': true
})).toEqual('booleanfalse=false&booleantrue=true');
expect(OC.buildQueryString({
2014-03-01 01:46:27 +00:00
'number': 123
})).toEqual('number=123');
});
});
describe('Session heartbeat', function() {
var clock,
oldConfig,
routeStub,
counter;
beforeEach(function() {
clock = sinon.useFakeTimers();
oldConfig = window.oc_config;
2014-03-05 00:10:39 +00:00
routeStub = sinon.stub(OC, 'generateUrl').returns('/heartbeat');
counter = 0;
fakeServer.autoRespond = true;
fakeServer.autoRespondAfter = 0;
fakeServer.respondWith(/\/heartbeat/, function(xhr) {
counter++;
xhr.respond(200, {'Content-Type': 'application/json'}, '{}');
});
$(document).off('ajaxComplete'); // ignore previously registered heartbeats
});
afterEach(function() {
clock.restore();
/* jshint camelcase: false */
window.oc_config = oldConfig;
routeStub.restore();
2015-12-10 17:08:40 +00:00
$(document).off('ajaxError');
$(document).off('ajaxComplete');
});
it('sends heartbeat half the session lifetime when heartbeat enabled', function() {
/* jshint camelcase: false */
window.oc_config = {
session_keepalive: true,
session_lifetime: 300
};
window.initCore();
2014-03-05 00:10:39 +00:00
expect(routeStub.calledWith('/heartbeat')).toEqual(true);
expect(counter).toEqual(0);
// less than half, still nothing
clock.tick(100 * 1000);
expect(counter).toEqual(0);
// reach past half (160), one call
clock.tick(55 * 1000);
expect(counter).toEqual(1);
// almost there to the next, still one
clock.tick(140 * 1000);
expect(counter).toEqual(1);
// past it, second call
clock.tick(20 * 1000);
expect(counter).toEqual(2);
});
it('does not send heartbeat when heartbeat disabled', function() {
/* jshint camelcase: false */
window.oc_config = {
session_keepalive: false,
session_lifetime: 300
};
window.initCore();
expect(routeStub.notCalled).toEqual(true);
expect(counter).toEqual(0);
clock.tick(1000000);
// still nothing
expect(counter).toEqual(0);
});
it('limits the heartbeat between one minute and one day', function() {
/* jshint camelcase: false */
var setIntervalStub = sinon.stub(window, 'setInterval');
window.oc_config = {
session_keepalive: true,
session_lifetime: 5
};
window.initCore();
expect(setIntervalStub.getCall(0).args[1]).toEqual(60 * 1000);
setIntervalStub.reset();
window.oc_config = {
session_keepalive: true,
session_lifetime: 48 * 3600
};
window.initCore();
expect(setIntervalStub.getCall(0).args[1]).toEqual(24 * 3600 * 1000);
setIntervalStub.restore();
});
});
describe('Parse query string', function() {
it('Parses query string from full URL', function() {
var query = OC.parseQueryString('http://localhost/stuff.php?q=a&b=x');
expect(query).toEqual({q: 'a', b: 'x'});
});
it('Parses query string from query part alone', function() {
var query = OC.parseQueryString('q=a&b=x');
expect(query).toEqual({q: 'a', b: 'x'});
});
it('Returns null hash when empty query', function() {
var query = OC.parseQueryString('');
expect(query).toEqual(null);
});
it('Returns empty hash when empty query with question mark', function() {
var query = OC.parseQueryString('?');
expect(query).toEqual({});
});
it('Decodes regular query strings', function() {
var query = OC.parseQueryString('a=abc&b=def');
expect(query).toEqual({
a: 'abc',
b: 'def'
});
});
it('Ignores empty parts', function() {
var query = OC.parseQueryString('&q=a&&b=x&');
expect(query).toEqual({q: 'a', b: 'x'});
});
it('Ignores lone equal signs', function() {
var query = OC.parseQueryString('&q=a&=&b=x&');
expect(query).toEqual({q: 'a', b: 'x'});
});
it('Includes extra equal signs in value', function() {
var query = OC.parseQueryString('u=a=x&q=a=b');
expect(query).toEqual({u: 'a=x', q: 'a=b'});
});
it('Decodes plus as space', function() {
var query = OC.parseQueryString('space+key=space+value');
expect(query).toEqual({'space key': 'space value'});
});
it('Decodes special characters', function() {
var query = OC.parseQueryString('unicode=%E6%B1%89%E5%AD%97');
expect(query).toEqual({unicode: '汉字'});
query = OC.parseQueryString('b=spaace%20value&space%20key=normalvalue&slash%2Fthis=amp%26ersand');
expect(query).toEqual({
b: 'spaace value',
'space key': 'normalvalue',
'slash/this': 'amp&ersand'
});
});
it('Decodes empty values', function() {
var query = OC.parseQueryString('keywithemptystring=&keywithnostring');
expect(query).toEqual({
'keywithemptystring': '',
'keywithnostring': null
});
});
it('Does not interpret data types', function() {
var query = OC.parseQueryString('booleanfalse=false&booleantrue=true&number=123');
expect(query).toEqual({
'booleanfalse': 'false',
'booleantrue': 'true',
'number': '123'
});
});
});
describe('Generate Url', function() {
it('returns absolute urls', function() {
expect(OC.generateUrl('heartbeat')).toEqual(OC.webroot + '/index.php/heartbeat');
expect(OC.generateUrl('/heartbeat')).toEqual(OC.webroot + '/index.php/heartbeat');
});
it('substitutes parameters which are escaped by default', function() {
expect(OC.generateUrl('apps/files/download/{file}', {file: '<">ImAnUnescapedString/!'})).toEqual(OC.webroot + '/index.php/apps/files/download/%3C%22%3EImAnUnescapedString%2F!');
});
it('substitutes parameters which can also be unescaped via option flag', function() {
expect(OC.generateUrl('apps/files/download/{file}', {file: 'subfolder/Welcome.txt'}, {escape: false})).toEqual(OC.webroot + '/index.php/apps/files/download/subfolder/Welcome.txt');
});
it('substitutes multiple parameters which are escaped by default', function() {
expect(OC.generateUrl('apps/files/download/{file}/{id}', {file: '<">ImAnUnescapedString/!', id: 5})).toEqual(OC.webroot + '/index.php/apps/files/download/%3C%22%3EImAnUnescapedString%2F!/5');
});
it('substitutes multiple parameters which can also be unescaped via option flag', function() {
expect(OC.generateUrl('apps/files/download/{file}/{id}', {file: 'subfolder/Welcome.txt', id: 5}, {escape: false})).toEqual(OC.webroot + '/index.php/apps/files/download/subfolder/Welcome.txt/5');
});
it('doesnt error out with no params provided', function () {
expect(OC.generateUrl('apps/files/download{file}')).toEqual(OC.webroot + '/index.php/apps/files/download%7Bfile%7D');
});
});
describe('Main menu mobile toggle', function() {
var clock;
var $toggle;
var $navigation;
beforeEach(function() {
jQuery.fx.off = true;
clock = sinon.useFakeTimers();
$('#testArea').append('<div id="header">' +
'<a class="menutoggle header-appname-container" href="#">' +
2015-03-26 16:10:59 +00:00
'<h1 class="header-appname"></h1>' +
'<div class="icon-caret"></div>' +
'</a>' +
'</div>' +
'<div id="navigation"></div>');
2014-06-04 22:40:15 +00:00
$toggle = $('#header').find('.menutoggle');
$navigation = $('#navigation');
});
afterEach(function() {
jQuery.fx.off = false;
clock.restore();
2015-12-10 17:08:40 +00:00
$(document).off('ajaxError');
});
it('Sets up menu toggle', function() {
window.initCore();
expect($navigation.hasClass('menu')).toEqual(true);
});
it('Clicking menu toggle toggles navigation in', function() {
window.initCore();
expect($navigation.is(':visible')).toEqual(false);
$toggle.click();
clock.tick(1 * 1000);
expect($navigation.is(':visible')).toEqual(true);
$toggle.click();
clock.tick(1 * 1000);
expect($navigation.is(':visible')).toEqual(false);
});
});
describe('SVG extension replacement', function() {
var svgSupportStub;
beforeEach(function() {
svgSupportStub = sinon.stub(OC.Util, 'hasSVGSupport');
});
afterEach(function() {
svgSupportStub.restore();
});
it('does not replace svg extension with png when SVG is supported', function() {
svgSupportStub.returns(true);
expect(
OC.Util.replaceSVGIcon('/path/to/myicon.svg?someargs=1')
).toEqual(
'/path/to/myicon.svg?someargs=1'
);
});
it('replaces svg extension with png when SVG not supported', function() {
svgSupportStub.returns(false);
expect(
OC.Util.replaceSVGIcon('/path/to/myicon.svg?someargs=1')
).toEqual(
'/path/to/myicon.png?someargs=1'
);
});
});
describe('Util', function() {
describe('humanFileSize', function() {
it('renders file sizes with the correct unit', function() {
var data = [
[0, '0 B'],
["0", '0 B'],
["A", 'NaN B'],
[125, '125 B'],
[128000, '125 KB'],
[128000000, '122.1 MB'],
[128000000000, '119.2 GB'],
[128000000000000, '116.4 TB']
];
for (var i = 0; i < data.length; i++) {
expect(OC.Util.humanFileSize(data[i][0])).toEqual(data[i][1]);
}
});
it('renders file sizes with the correct unit for small sizes', function() {
var data = [
[0, '0 KB'],
[125, '< 1 KB'],
[128000, '125 KB'],
[128000000, '122.1 MB'],
[128000000000, '119.2 GB'],
[128000000000000, '116.4 TB']
];
for (var i = 0; i < data.length; i++) {
expect(OC.Util.humanFileSize(data[i][0], true)).toEqual(data[i][1]);
}
});
});
describe('stripTime', function() {
it('strips time from dates', function() {
expect(OC.Util.stripTime(new Date(2014, 2, 24, 15, 4, 45, 24)))
.toEqual(new Date(2014, 2, 24, 0, 0, 0, 0));
});
});
});
describe('naturalSortCompare', function() {
// cit() will skip tests if running on PhantomJS because it has issues with
// localeCompare(). See https://github.com/ariya/phantomjs/issues/11063
//
// Please make sure to run these tests in Chrome/Firefox manually
// to make sure they run.
var cit = window.isPhantom?xit:it;
// must provide the same results as \OC_Util::naturalSortCompare
it('sorts alphabetically', function() {
var a = [
'def',
'xyz',
'abc'
];
a.sort(OC.Util.naturalSortCompare);
expect(a).toEqual([
'abc',
'def',
'xyz'
]);
});
cit('sorts with different casing', function() {
var a = [
'aaa',
'bbb',
'BBB',
'AAA'
];
a.sort(OC.Util.naturalSortCompare);
expect(a).toEqual([
'aaa',
'AAA',
'bbb',
'BBB'
]);
});
it('sorts with numbers', function() {
var a = [
'124.txt',
'abc1',
'123.txt',
'abc',
'abc2',
'def (2).txt',
'ghi 10.txt',
'abc12',
'def.txt',
'def (1).txt',
'ghi 2.txt',
'def (10).txt',
'abc10',
'def (12).txt',
'z',
'ghi.txt',
'za',
'ghi 1.txt',
'ghi 12.txt',
2014-07-23 10:52:13 +00:00
'zz',
'15.txt',
'15b.txt'
];
a.sort(OC.Util.naturalSortCompare);
expect(a).toEqual([
2014-07-23 10:52:13 +00:00
'15.txt',
'15b.txt',
'123.txt',
'124.txt',
'abc',
'abc1',
'abc2',
'abc10',
'abc12',
'def.txt',
'def (1).txt',
'def (2).txt',
'def (10).txt',
'def (12).txt',
'ghi.txt',
'ghi 1.txt',
'ghi 2.txt',
'ghi 10.txt',
'ghi 12.txt',
'z',
'za',
'zz'
]);
});
it('sorts with chinese characters', function() {
var a = [
'十.txt',
'一.txt',
'二.txt',
'十 2.txt',
'三.txt',
'四.txt',
'abc.txt',
'五.txt',
'七.txt',
'八.txt',
'九.txt',
'六.txt',
'十一.txt',
'波.txt',
'破.txt',
'莫.txt',
'啊.txt',
'123.txt'
];
a.sort(OC.Util.naturalSortCompare);
expect(a).toEqual([
'123.txt',
'abc.txt',
'一.txt',
'七.txt',
'三.txt',
'九.txt',
'二.txt',
'五.txt',
'八.txt',
'六.txt',
'十.txt',
'十 2.txt',
'十一.txt',
'啊.txt',
'四.txt',
'波.txt',
'破.txt',
'莫.txt'
]);
});
cit('sorts with umlauts', function() {
var a = [
'öh.txt',
'Äh.txt',
'oh.txt',
'Üh 2.txt',
'Üh.txt',
'ah.txt',
'Öh.txt',
'uh.txt',
'üh.txt',
'äh.txt'
];
a.sort(OC.Util.naturalSortCompare);
expect(a).toEqual([
'ah.txt',
'äh.txt',
'Äh.txt',
'oh.txt',
'öh.txt',
'Öh.txt',
'uh.txt',
'üh.txt',
'Üh.txt',
'Üh 2.txt'
]);
});
});
2014-12-01 15:17:28 +00:00
describe('Plugins', function() {
var plugin;
beforeEach(function() {
plugin = {
name: 'Some name',
attach: function(obj) {
obj.attached = true;
},
detach: function(obj) {
obj.attached = false;
}
};
OC.Plugins.register('OC.Test.SomeName', plugin);
});
it('attach plugin to object', function() {
var obj = {something: true};
OC.Plugins.attach('OC.Test.SomeName', obj);
expect(obj.attached).toEqual(true);
OC.Plugins.detach('OC.Test.SomeName', obj);
expect(obj.attached).toEqual(false);
});
it('only call handler for target name', function() {
var obj = {something: true};
OC.Plugins.attach('OC.Test.SomeOtherName', obj);
expect(obj.attached).not.toBeDefined();
OC.Plugins.detach('OC.Test.SomeOtherName', obj);
expect(obj.attached).not.toBeDefined();
});
});
describe('Notifications', function() {
var showSpy;
var showHtmlSpy;
var hideSpy;
var clock;
beforeEach(function() {
clock = sinon.useFakeTimers();
showSpy = sinon.spy(OC.Notification, 'show');
showHtmlSpy = sinon.spy(OC.Notification, 'showHtml');
hideSpy = sinon.spy(OC.Notification, 'hide');
$('#testArea').append('<div id="notification"></div>');
});
afterEach(function() {
showSpy.restore();
showHtmlSpy.restore();
hideSpy.restore();
// jump past animations
clock.tick(10000);
clock.restore();
});
describe('showTemporary', function() {
it('shows a plain text notification with default timeout', function() {
var $row = OC.Notification.showTemporary('My notification test');
expect(showSpy.calledOnce).toEqual(true);
expect(showSpy.firstCall.args[0]).toEqual('My notification test');
expect(showSpy.firstCall.args[1]).toEqual({isHTML: false, timeout: 7});
expect($row).toBeDefined();
expect($row.text()).toEqual('My notification test');
});
it('shows a HTML notification with default timeout', function() {
var $row = OC.Notification.showTemporary('<a>My notification test</a>', { isHTML: true });
expect(showSpy.notCalled).toEqual(true);
expect(showHtmlSpy.calledOnce).toEqual(true);
expect(showHtmlSpy.firstCall.args[0]).toEqual('<a>My notification test</a>');
expect(showHtmlSpy.firstCall.args[1]).toEqual({isHTML: true, timeout: 7});
expect($row).toBeDefined();
expect($row.text()).toEqual('My notification test');
});
it('hides itself after 7 seconds', function() {
var $row = OC.Notification.showTemporary('');
// travel in time +7000 milliseconds
clock.tick(7000);
expect(hideSpy.calledOnce).toEqual(true);
expect(hideSpy.firstCall.args[0]).toEqual($row);
});
});
describe('show', function() {
it('hides itself after a given time', function() {
OC.Notification.show('', { timeout: 10 });
// travel in time +9 seconds
clock.tick(9000);
expect(hideSpy.notCalled).toEqual(true);
// travel in time +1 seconds
clock.tick(1000);
expect(hideSpy.calledOnce).toEqual(true);
});
it('does not hide itself after a given time if a timeout of 0 is defined', function() {
OC.Notification.show('', { timeout: 0 });
// travel in time +1000 seconds
clock.tick(1000000);
expect(hideSpy.notCalled).toEqual(true);
});
it('does not hide itself if no timeout given to show', function() {
OC.Notification.show('');
// travel in time +1000 seconds
clock.tick(1000000);
expect(hideSpy.notCalled).toEqual(true);
});
});
it('cumulates several notifications', function() {
var $row1 = OC.Notification.showTemporary('One');
var $row2 = OC.Notification.showTemporary('Two', {timeout: 2});
var $row3 = OC.Notification.showTemporary('Three');
var $el = $('#notification');
var $rows = $el.find('.row');
expect($rows.length).toEqual(3);
expect($rows.eq(0).is($row1)).toEqual(true);
expect($rows.eq(1).is($row2)).toEqual(true);
expect($rows.eq(2).is($row3)).toEqual(true);
clock.tick(3000);
$rows = $el.find('.row');
expect($rows.length).toEqual(2);
expect($rows.eq(0).is($row1)).toEqual(true);
expect($rows.eq(1).is($row3)).toEqual(true);
});
it('shows close button for error types', function() {
var $row = OC.Notification.showTemporary('One');
var $rowError = OC.Notification.showTemporary('Two', {type: 'error'});
expect($row.find('.close').length).toEqual(0);
expect($rowError.find('.close').length).toEqual(1);
// after clicking, row is gone
$rowError.find('.close').click();
var $rows = $('#notification').find('.row');
expect($rows.length).toEqual(1);
expect($rows.eq(0).is($row)).toEqual(true);
});
it('fades out the last notification but not the other ones', function() {
var fadeOutStub = sinon.stub($.fn, 'fadeOut');
var $row1 = OC.Notification.show('One', {type: 'error'});
var $row2 = OC.Notification.show('Two', {type: 'error'});
OC.Notification.showTemporary('Three', {timeout: 2});
var $el = $('#notification');
var $rows = $el.find('.row');
expect($rows.length).toEqual(3);
clock.tick(3000);
$rows = $el.find('.row');
expect($rows.length).toEqual(2);
$row1.find('.close').click();
clock.tick(1000);
expect(fadeOutStub.notCalled).toEqual(true);
$row2.find('.close').click();
clock.tick(1000);
expect(fadeOutStub.calledOnce).toEqual(true);
expect($el.is(':empty')).toEqual(false);
fadeOutStub.yield();
expect($el.is(':empty')).toEqual(true);
fadeOutStub.restore();
});
it('hides the first notification when calling hide without arguments', function() {
var $row1 = OC.Notification.show('One');
var $row2 = OC.Notification.show('Two');
var $el = $('#notification');
var $rows = $el.find('.row');
expect($rows.length).toEqual(2);
OC.Notification.hide();
$rows = $el.find('.row');
expect($rows.length).toEqual(1);
expect($rows.eq(0).is($row2)).toEqual(true);
});
it('hides the given notification when calling hide with argument', function() {
var $row1 = OC.Notification.show('One');
var $row2 = OC.Notification.show('Two');
var $el = $('#notification');
var $rows = $el.find('.row');
expect($rows.length).toEqual(2);
OC.Notification.hide($row2);
$rows = $el.find('.row');
expect($rows.length).toEqual(1);
expect($rows.eq(0).is($row1)).toEqual(true);
});
});
2015-12-10 17:08:40 +00:00
describe('global ajax errors', function() {
var reloadStub, ajaxErrorStub, clock;
2016-04-20 21:09:59 +00:00
var notificationStub;
var waitTimeMs = 6000;
2015-12-10 17:08:40 +00:00
beforeEach(function() {
clock = sinon.useFakeTimers();
2015-12-10 17:08:40 +00:00
reloadStub = sinon.stub(OC, 'reload');
2016-04-20 21:09:59 +00:00
notificationStub = sinon.stub(OC.Notification, 'show');
2015-12-10 17:08:40 +00:00
// unstub the error processing method
ajaxErrorStub = OC._processAjaxError;
ajaxErrorStub.restore();
window.initCore();
});
afterEach(function() {
reloadStub.restore();
2016-04-20 21:09:59 +00:00
notificationStub.restore();
clock.restore();
2015-12-10 17:08:40 +00:00
});
it('reloads current page in case of auth error', function() {
2015-12-10 17:08:40 +00:00
var dataProvider = [
[200, false],
[400, false],
[0, true],
2015-12-10 17:08:40 +00:00
[401, true],
[302, true],
[303, true],
2015-12-10 17:08:40 +00:00
[307, true]
];
for (var i = 0; i < dataProvider.length; i++) {
var xhr = { status: dataProvider[i][0] };
var expectedCall = dataProvider[i][1];
reloadStub.reset();
OC._reloadCalled = false;
2015-12-10 17:08:40 +00:00
$(document).trigger(new $.Event('ajaxError'), xhr);
// trigger timers
2016-04-20 21:09:59 +00:00
clock.tick(waitTimeMs);
2015-12-10 17:08:40 +00:00
if (expectedCall) {
expect(reloadStub.calledOnce).toEqual(true);
} else {
expect(reloadStub.notCalled).toEqual(true);
}
}
});
it('reload only called once in case of auth error', function() {
var xhr = { status: 401 };
$(document).trigger(new $.Event('ajaxError'), xhr);
$(document).trigger(new $.Event('ajaxError'), xhr);
// trigger timers
2016-04-20 21:09:59 +00:00
clock.tick(waitTimeMs);
expect(reloadStub.calledOnce).toEqual(true);
});
it('does not reload the page if the user was navigating away', function() {
var xhr = { status: 0 };
OC._userIsNavigatingAway = true;
clock.tick(100);
$(document).trigger(new $.Event('ajaxError'), xhr);
2016-04-20 21:09:59 +00:00
clock.tick(waitTimeMs);
expect(reloadStub.notCalled).toEqual(true);
});
2016-04-20 21:09:59 +00:00
it('displays notification', function() {
var xhr = { status: 401 };
$(document).trigger(new $.Event('ajaxError'), xhr);
clock.tick(waitTimeMs);
expect(notificationStub.calledOnce).toEqual(true);
});
});
});