aboutsummaryrefslogtreecommitdiffstats
path: root/core/js
diff options
context:
space:
mode:
Diffstat (limited to 'core/js')
-rw-r--r--core/js/config.php6
-rw-r--r--core/js/core.json43
-rw-r--r--core/js/js.js87
-rw-r--r--core/js/tests/specHelper.js18
-rw-r--r--core/js/tests/specs/coreSpec.js210
5 files changed, 324 insertions, 40 deletions
diff --git a/core/js/config.php b/core/js/config.php
index dd46f7889d1..517ea1615a8 100644
--- a/core/js/config.php
+++ b/core/js/config.php
@@ -55,6 +55,12 @@ $array = array(
)
),
"firstDay" => json_encode($l->l('firstday', 'firstday')) ,
+ "oc_config" => json_encode(
+ array(
+ 'session_lifetime' => \OCP\Config::getSystemValue('session_lifetime', 60 * 60 * 24),
+ 'session_keepalive' => \OCP\Config::getSystemValue('session_keepalive', true)
+ )
+ )
);
// Echo it
diff --git a/core/js/core.json b/core/js/core.json
index 79cfc42f587..4beab7cf796 100644
--- a/core/js/core.json
+++ b/core/js/core.json
@@ -1,28 +1,23 @@
{
+ "libraries": [
+ "jquery-1.10.0.min.js",
+ "jquery-migrate-1.2.1.min.js",
+ "jquery-ui-1.10.0.custom.js",
+ "jquery-showpassword.js",
+ "jquery.infieldlabel.js",
+ "jquery.placeholder.js",
+ "jquery-tipsy.js"
+ ],
"modules": [
- "jquery-1.10.0.min.js",
- "jquery-migrate-1.2.1.min.js",
- "jquery-ui-1.10.0.custom.js",
- "jquery-showpassword.js",
- "jquery.infieldlabel.js",
- "jquery.placeholder.js",
- "jquery-tipsy.js",
- "compatibility.js",
- "jquery.ocdialog.js",
- "oc-dialogs.js",
- "js.js",
- "octemplate.js",
- "eventsource.js",
- "config.js",
- "multiselect.js",
- "search.js",
- "router.js",
- "oc-requesttoken.js",
- "styles.js",
- "apps.js",
- "fixes.js",
- "jquery-ui-2.10.0.custom.js",
- "jquery-tipsy.js",
- "jquery.ocdialog.js"
+ "compatibility.js",
+ "jquery.ocdialog.js",
+ "oc-dialogs.js",
+ "js.js",
+ "octemplate.js",
+ "eventsource.js",
+ "config.js",
+ "multiselect.js",
+ "router.js",
+ "oc-requesttoken.js"
]
}
diff --git a/core/js/js.js b/core/js/js.js
index e84f482d672..cb177712a3a 100644
--- a/core/js/js.js
+++ b/core/js/js.js
@@ -11,6 +11,8 @@ var oc_webroot;
var oc_current_user = document.getElementsByTagName('head')[0].getAttribute('data-user');
var oc_requesttoken = document.getElementsByTagName('head')[0].getAttribute('data-requesttoken');
+window.oc_config = window.oc_config || {};
+
if (typeof oc_webroot === "undefined") {
oc_webroot = location.pathname;
var pos = oc_webroot.indexOf('/index.php/');
@@ -253,6 +255,12 @@ var OC={
return link;
},
/**
+ * Redirect to the target URL, can also be used for downloads.
+ */
+ redirect: function(targetUrl) {
+ window.location = targetUrl;
+ },
+ /**
* get the absolute path to an image file
* @param app the app id to which the image belongs
* @param file the name of the image file
@@ -364,6 +372,34 @@ var OC={
}
return result;
},
+
+ /**
+ * Builds a URL query from a JS map.
+ * @param params parameter map
+ * @return string containing a URL query (without question) mark
+ */
+ buildQueryString: function(params) {
+ var s = '';
+ var first = true;
+ if (!params) {
+ return s;
+ }
+ for (var key in params) {
+ var value = params[key];
+ if (first) {
+ first = false;
+ }
+ else {
+ s += '&';
+ }
+ s += encodeURIComponent(key);
+ if (value !== null && typeof(value) !== 'undefined') {
+ s += '=' + encodeURIComponent(value);
+ }
+ }
+ return s;
+ },
+
/**
* Opens a popup with the setting for an app.
* @param appid String. The ID of the app e.g. 'calendar', 'contacts' or 'files'.
@@ -708,8 +744,39 @@ function fillWindow(selector) {
console.warn("This function is deprecated! Use CSS instead");
}
-$(document).ready(function(){
- sessionHeartBeat();
+/**
+ * Initializes core
+ */
+function initCore() {
+
+ /**
+ * Calls the server periodically to ensure that session doesn't
+ * time out
+ */
+ function initSessionHeartBeat(){
+ // interval in seconds
+ var interval = 900;
+ if (oc_config.session_lifetime) {
+ interval = Math.floor(oc_config.session_lifetime / 2);
+ }
+ // minimum one minute
+ if (interval < 60) {
+ interval = 60;
+ }
+ OC.Router.registerLoadedCallback(function(){
+ var url = OC.Router.generate('heartbeat');
+ setInterval(function(){
+ $.post(url);
+ }, interval * 1000);
+ });
+ }
+
+ // session heartbeat (defaults to enabled)
+ if (typeof(oc_config.session_keepalive) === 'undefined' ||
+ !!oc_config.session_keepalive) {
+
+ initSessionHeartBeat();
+ }
if(!SVGSupport()){ //replace all svg images with png images for browser that dont support svg
replaceSVG();
@@ -822,7 +889,9 @@ $(document).ready(function(){
$('input[type=text]').focus(function(){
this.select();
});
-});
+}
+
+$(document).ready(initCore);
/**
* Filter Jquery selector by attribute value
@@ -952,15 +1021,3 @@ jQuery.fn.exists = function(){
return this.length > 0;
};
-/**
- * Calls the server periodically every 15 mins to ensure that session doesnt
- * time out
- */
-function sessionHeartBeat(){
- OC.Router.registerLoadedCallback(function(){
- var url = OC.Router.generate('heartbeat');
- setInterval(function(){
- $.post(url);
- }, 900000);
- });
-}
diff --git a/core/js/tests/specHelper.js b/core/js/tests/specHelper.js
index 4a30878df51..1848d08354e 100644
--- a/core/js/tests/specHelper.js
+++ b/core/js/tests/specHelper.js
@@ -19,6 +19,8 @@
*
*/
+/* global OC */
+
/**
* Simulate the variables that are normally set by PHP code
*/
@@ -57,10 +59,15 @@ window.oc_webroot = location.href + '/';
window.oc_appswebroots = {
"files": window.oc_webroot + '/apps/files/'
};
+window.oc_config = {
+ session_lifetime: 600 * 1000,
+ session_keepalive: false
+};
// global setup for all tests
(function setupTests() {
- var fakeServer = null;
+ var fakeServer = null,
+ routesRequestStub;
beforeEach(function() {
// enforce fake XHR, tests should not depend on the server and
@@ -78,9 +85,18 @@ window.oc_appswebroots = {
// make it globally available, so that other tests can define
// custom responses
window.fakeServer = fakeServer;
+
+ OC.Router.routes = [];
+ OC.Router.routes_request = {
+ state: sinon.stub().returns('resolved'),
+ done: sinon.stub()
+ };
});
afterEach(function() {
+ OC.Router.routes_request.state.reset();
+ OC.Router.routes_request.done.reset();
+
// uncomment this to log requests
// console.log(window.fakeServer.requests);
fakeServer.restore();
diff --git a/core/js/tests/specs/coreSpec.js b/core/js/tests/specs/coreSpec.js
index 827669f270b..478505e9287 100644
--- a/core/js/tests/specs/coreSpec.js
+++ b/core/js/tests/specs/coreSpec.js
@@ -18,6 +18,8 @@
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
+
+/* global OC */
describe('Core base tests', function() {
describe('Base values', function() {
it('Sets webroots', function() {
@@ -25,6 +27,103 @@ describe('Core base tests', function() {
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');
+ });
+ });
describe('Link functions', function() {
var TESTAPP = 'testapp';
var TESTAPP_ROOT = OC.webroot + '/appsx/testapp';
@@ -67,4 +166,115 @@ describe('Core base tests', function() {
});
});
});
+ 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({
+ unicode: '汉字',
+ })).toEqual('unicode=%E6%B1%89%E5%AD%97');
+ expect(OC.buildQueryString({
+ 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': '',
+ 'keywithnull': null,
+ 'keywithundefined': null,
+ something: 'else'
+ })).toEqual('keywithemptystring=&keywithnull&keywithundefined&something=else');
+ expect(OC.buildQueryString({
+ 'booleanfalse': false,
+ 'booleantrue': true
+ })).toEqual('booleanfalse=false&booleantrue=true');
+ expect(OC.buildQueryString({
+ 'number': 123,
+ })).toEqual('number=123');
+ });
+ });
+ describe('Session heartbeat', function() {
+ var clock,
+ oldConfig,
+ loadedStub,
+ routeStub,
+ counter;
+
+ beforeEach(function() {
+ clock = sinon.useFakeTimers();
+ oldConfig = window.oc_config;
+ loadedStub = sinon.stub(OC.Router, 'registerLoadedCallback');
+ routeStub = sinon.stub(OC.Router, 'generate').returns('/heartbeat');
+ counter = 0;
+
+ fakeServer.autoRespond = true;
+ fakeServer.autoRespondAfter = 0;
+ fakeServer.respondWith(/\/heartbeat/, function(xhr) {
+ counter++;
+ xhr.respond(200, {'Content-Type': 'application/json'}, '{}');
+ });
+ });
+ afterEach(function() {
+ clock.restore();
+ window.oc_config = oldConfig;
+ loadedStub.restore();
+ routeStub.restore();
+ });
+ it('sends heartbeat half the session lifetime when heartbeat enabled', function() {
+ window.oc_config = {
+ session_keepalive: true,
+ session_lifetime: 300
+ };
+ window.initCore();
+ expect(loadedStub.calledOnce).toEqual(true);
+ loadedStub.yield();
+ 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 no send heartbeat when heartbeat disabled', function() {
+ window.oc_config = {
+ session_keepalive: false,
+ session_lifetime: 300
+ };
+ window.initCore();
+ expect(loadedStub.notCalled).toEqual(true);
+ expect(routeStub.notCalled).toEqual(true);
+
+ expect(counter).toEqual(0);
+
+ clock.tick(1000000);
+
+ // still nothing
+ expect(counter).toEqual(0);
+ });
+
+ });
});
+