Added Javascript unit tests
- added karma utility to run jasmine unit tests - added Sinon library (for stubs/mocks/fakeserver) - added a few unit tests for core and files - added autotest-js.sh script
This commit is contained in:
parent
85e00ad35a
commit
350214c609
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* 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('FileList tests', function() {
|
||||
beforeEach(function() {
|
||||
// init horrible parameters
|
||||
$('<input type="hidden" id="dir" value="/subdir"></input>').append('body');
|
||||
$('<input type="hidden" id="permissions" value="31"></input>').append('body');
|
||||
});
|
||||
afterEach(function() {
|
||||
$('#dir, #permissions').remove();
|
||||
});
|
||||
it('generates file element with correct attributes when calling addFile', function() {
|
||||
var lastMod = new Date(10000);
|
||||
var $tr = FileList.addFile('testName.txt', 1234, lastMod, false, false, {download_url: 'test/download/url'});
|
||||
|
||||
expect($tr).toBeDefined();
|
||||
expect($tr[0].tagName.toLowerCase()).toEqual('tr');
|
||||
expect($tr.attr('data-type')).toEqual('file');
|
||||
expect($tr.attr('data-file')).toEqual('testName.txt');
|
||||
expect($tr.attr('data-size')).toEqual('1234');
|
||||
//expect($tr.attr('data-permissions')).toEqual('31');
|
||||
//expect($tr.attr('data-mime')).toEqual('plain/text');
|
||||
});
|
||||
it('generates dir element with correct attributes when calling addDir', function() {
|
||||
var lastMod = new Date(10000);
|
||||
var $tr = FileList.addDir('testFolder', 1234, lastMod, false);
|
||||
|
||||
expect($tr).toBeDefined();
|
||||
expect($tr[0].tagName.toLowerCase()).toEqual('tr');
|
||||
expect($tr.attr('data-type')).toEqual('dir');
|
||||
expect($tr.attr('data-file')).toEqual('testFolder');
|
||||
expect($tr.attr('data-size')).toEqual('1234');
|
||||
//expect($tr.attr('data-permissions')).toEqual('31');
|
||||
//expect($tr.attr('data-mime')).toEqual('httpd/unix-directory');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
* 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('Files tests', function() {
|
||||
describe('File name validation', function() {
|
||||
it('Validates correct file names', function() {
|
||||
var fileNames = [
|
||||
'boringname',
|
||||
'something.with.extension',
|
||||
'now with spaces',
|
||||
'.a',
|
||||
'..a',
|
||||
'.dotfile',
|
||||
'single\'quote',
|
||||
' spaces before',
|
||||
'spaces after ',
|
||||
'allowed chars including the crazy ones $%&_-^@!,()[]{}=;#',
|
||||
'汉字也能用',
|
||||
'und Ümläüte sind auch willkommen'
|
||||
];
|
||||
for ( var i = 0; i < fileNames.length; i++ ) {
|
||||
try {
|
||||
expect(Files.isFileNameValid(fileNames[i])).toEqual(true);
|
||||
}
|
||||
catch (e) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
});
|
||||
it('Detects invalid file names', function() {
|
||||
var fileNames = [
|
||||
'',
|
||||
' ',
|
||||
'.',
|
||||
'..',
|
||||
'back\\slash',
|
||||
'sl/ash',
|
||||
'lt<lt',
|
||||
'gt>gt',
|
||||
'col:on',
|
||||
'double"quote',
|
||||
'pi|pe',
|
||||
'dont?ask?questions?',
|
||||
'super*star',
|
||||
'new\nline',
|
||||
' ..',
|
||||
'.. ',
|
||||
'. ',
|
||||
' .'
|
||||
];
|
||||
for ( var i = 0; i < fileNames.length; i++ ) {
|
||||
var threwException = false;
|
||||
try {
|
||||
Files.isFileNameValid(fileNames[i]);
|
||||
fail();
|
||||
}
|
||||
catch (e) {
|
||||
threwException = true;
|
||||
}
|
||||
expect(threwException).toEqual(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,37 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# ownCloud
|
||||
#
|
||||
# Run JS tests
|
||||
#
|
||||
# @author Vincent Petry
|
||||
# @copyright 2014 Vincent Petry <pvince81@owncloud.com>
|
||||
#
|
||||
NPM="$(which npm 2>/dev/null)"
|
||||
PREFIX="build"
|
||||
|
||||
if test -z "$NPM"
|
||||
then
|
||||
echo 'Node JS >= 0.8 is required to run the JavaScript tests' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# update/install test packages
|
||||
mkdir -p "$PREFIX" && $NPM install --link --prefix "$PREFIX" || exit 3
|
||||
|
||||
KARMA="$(which karma 2>/dev/null)"
|
||||
|
||||
# If not installed globally, try local version
|
||||
if test -z "$KARMA"
|
||||
then
|
||||
KARMA="$PREFIX/node_modules/karma/bin/karma"
|
||||
fi
|
||||
|
||||
if test -z "$KARMA"
|
||||
then
|
||||
echo 'Karma module executable not found' >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
KARMA_TESTSUITE="$1" $KARMA start tests/karma.config.js --single-run
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "owncloud-js-tests",
|
||||
"description": "ownCloud tests",
|
||||
"version": "0.0.1",
|
||||
"author": {
|
||||
"name": "Vincent Petry",
|
||||
"email": "pvince81@owncloud.com"
|
||||
},
|
||||
"private": true,
|
||||
"homepage": "https://github.com/owncloud/",
|
||||
"contributors": [],
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"karma": "*",
|
||||
"karma-jasmine": "*",
|
||||
"karma-junit-reporter": "*"
|
||||
},
|
||||
"engine": "node >= 0.8"
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"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"
|
||||
]
|
||||
}
|
|
@ -3,9 +3,12 @@ OC.Router = {
|
|||
// register your ajax requests to load after the loading of the routes
|
||||
// has finished. otherwise you face problems with race conditions
|
||||
registerLoadedCallback: function(callback){
|
||||
if (!this.routes_request){
|
||||
return;
|
||||
}
|
||||
this.routes_request.done(callback);
|
||||
},
|
||||
routes_request: $.ajax(OC.router_base_url + '/core/routes.json', {
|
||||
routes_request: !window.TESTING && $.ajax(OC.router_base_url + '/core/routes.json', {
|
||||
dataType: 'json',
|
||||
success: function(jsondata) {
|
||||
if (jsondata.status === 'success') {
|
||||
|
@ -75,4 +78,4 @@ OC.Router = {
|
|||
|
||||
return OC.router_base_url + url;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,89 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Simulate the variables that are normally set by PHP code
|
||||
*/
|
||||
|
||||
// from core/js/config.php
|
||||
window.TESTING = true;
|
||||
window.oc_debug = true;
|
||||
window.datepickerFormatDate = 'MM d, yy';
|
||||
window.dayNames = [
|
||||
'Sunday',
|
||||
'Monday',
|
||||
'Tuesday',
|
||||
'Wednesday',
|
||||
'Thursday',
|
||||
'Friday',
|
||||
'Saturday'
|
||||
];
|
||||
window.monthNames = [
|
||||
'January',
|
||||
'February',
|
||||
'March',
|
||||
'April',
|
||||
'May',
|
||||
'June',
|
||||
'July',
|
||||
'August',
|
||||
'September',
|
||||
'October',
|
||||
'November',
|
||||
'December'
|
||||
];
|
||||
window.firstDay = 0;
|
||||
|
||||
// setup dummy webroots
|
||||
window.oc_webroot = location.href + '/';
|
||||
window.oc_appswebroots = {
|
||||
"files": window.oc_webroot + '/apps/files/'
|
||||
};
|
||||
|
||||
// global setup for all tests
|
||||
(function setupTests() {
|
||||
var fakeServer = null;
|
||||
|
||||
beforeEach(function() {
|
||||
// enforce fake XHR, tests should not depend on the server and
|
||||
// must use fake responses for expected calls
|
||||
fakeServer = sinon.fakeServer.create();
|
||||
|
||||
// return fake translations as they might be requested for many test runs
|
||||
fakeServer.respondWith(/\/index.php\/core\/ajax\/translations.php$/, [
|
||||
200, {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
'{"data": [], "plural_form": "nplurals=2; plural=(n != 1);"}'
|
||||
]);
|
||||
|
||||
// make it globally available, so that other tests can define
|
||||
// custom responses
|
||||
window.fakeServer = fakeServer;
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
// uncomment this to log requests
|
||||
// console.log(window.fakeServer.requests);
|
||||
fakeServer.restore();
|
||||
});
|
||||
})();
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* 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() {
|
||||
describe('Base values', function() {
|
||||
it('Sets webroots', function() {
|
||||
expect(OC.webroot).toBeDefined();
|
||||
expect(OC.appswebroots).toBeDefined();
|
||||
});
|
||||
});
|
||||
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(window, 'SVGSupport', 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(window, 'SVGSupport', 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(window, 'SVGSupport', 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();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -293,6 +293,7 @@ class OC {
|
|||
|
||||
public static function initTemplateEngine() {
|
||||
// Add the stuff we need always
|
||||
// TODO: read from core/js/core.json
|
||||
OC_Util::addScript("jquery-1.10.0.min");
|
||||
OC_Util::addScript("jquery-migrate-1.2.1.min");
|
||||
OC_Util::addScript("jquery-ui-1.10.0.custom");
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This node module is run by the karma executable to specify its configuration.
|
||||
*
|
||||
* The list of files from all needed JavaScript files including the ones from the
|
||||
* apps to test, and the test specs will be passed as configuration object.
|
||||
*
|
||||
* Note that it is possible to test a single app by setting the KARMA_TESTSUITE
|
||||
* environment variable to the apps name, for example "core" or "files_encryption".
|
||||
* Multiple apps can be specified by separating them with space.
|
||||
*
|
||||
*/
|
||||
module.exports = function(config) {
|
||||
|
||||
// default apps to test when none is specified (TODO: read from filesystem ?)
|
||||
var defaultApps = 'core files';
|
||||
var appsToTest = process.env.KARMA_TESTSUITE || defaultApps;
|
||||
|
||||
// read core files from core.json,
|
||||
// these are required by all apps so always need to be loaded
|
||||
// note that the loading order is important that's why they
|
||||
// are specified in a separate file
|
||||
var corePath = 'core/js/';
|
||||
var coreFiles = require('../' + corePath + 'core.json').modules;
|
||||
var testCore = false;
|
||||
var files = [];
|
||||
var index;
|
||||
|
||||
// find out what apps to test from appsToTest
|
||||
appsToTest = appsToTest.split(' ');
|
||||
index = appsToTest.indexOf('core');
|
||||
if (index > -1) {
|
||||
appsToTest.splice(index, 1);
|
||||
testCore = true;
|
||||
}
|
||||
|
||||
// extra test libs
|
||||
files.push(corePath + 'tests/lib/sinon-1.7.3.js');
|
||||
|
||||
// core mocks
|
||||
files.push(corePath + 'tests/specHelper.js');
|
||||
|
||||
// add core files
|
||||
for ( var i = 0; i < coreFiles.length; i++ ) {
|
||||
files.push( corePath + coreFiles[i] );
|
||||
}
|
||||
|
||||
// need to test the core app as well ?
|
||||
if (testCore) {
|
||||
// core tests
|
||||
files.push(corePath + 'tests/specs/*.js');
|
||||
}
|
||||
|
||||
for ( var i = 0; i < appsToTest.length; i++ ) {
|
||||
// add app JS
|
||||
files.push('apps/' + appsToTest[i] + '/js/*.js');
|
||||
// add test specs
|
||||
files.push('apps/' + appsToTest[i] + '/tests/js/*.js');
|
||||
}
|
||||
|
||||
config.set({
|
||||
|
||||
// base path, that will be used to resolve files and exclude
|
||||
basePath: '..',
|
||||
|
||||
|
||||
// frameworks to use
|
||||
frameworks: ['jasmine'],
|
||||
|
||||
// list of files / patterns to load in the browser
|
||||
files: files,
|
||||
|
||||
// list of files to exclude
|
||||
exclude: [
|
||||
|
||||
],
|
||||
|
||||
// test results reporter to use
|
||||
// possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
|
||||
reporters: ['dots', 'junit'],
|
||||
|
||||
junitReporter: {
|
||||
outputFile: 'tests/autotest-results-js.xml'
|
||||
},
|
||||
|
||||
// web server port
|
||||
port: 9876,
|
||||
|
||||
|
||||
// enable / disable colors in the output (reporters and logs)
|
||||
colors: true,
|
||||
|
||||
|
||||
// level of logging
|
||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||
logLevel: config.LOG_INFO,
|
||||
|
||||
// enable / disable watching file and executing tests whenever any file changes
|
||||
autoWatch: false,
|
||||
|
||||
// Start these browsers, currently available:
|
||||
// - Chrome
|
||||
// - ChromeCanary
|
||||
// - Firefox
|
||||
// - Opera (has to be installed with `npm install karma-opera-launcher`)
|
||||
// - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`)
|
||||
// - PhantomJS
|
||||
// - IE (only Windows; has to be installed with `npm install karma-ie-launcher`)
|
||||
browsers: ['PhantomJS'],
|
||||
|
||||
// If browser does not capture in given timeout [ms], kill it
|
||||
captureTimeout: 60000,
|
||||
|
||||
// Continuous Integration mode
|
||||
// if true, it capture browsers, run tests and exit
|
||||
singleRun: false
|
||||
});
|
||||
};
|
Loading…
Reference in New Issue