From 5d9feb0fb30d829575fd38ee55de53a92e32505e Mon Sep 17 00:00:00 2001 From: vdice Date: Mon, 8 Jun 2015 14:17:36 -0600 Subject: [PATCH] bootstrap unit tests --- Makefile | 15 +- coffeelint.json | 129 +++++ karma.conf.coffee | 49 ++ libs/app.bundle.js | 893 ++++++++++++++++++---------------- package.json | 19 +- test/spec/SettingsSpec.coffee | 64 +++ test/spec/UIUtilSpec.coffee | 16 + 7 files changed, 751 insertions(+), 434 deletions(-) create mode 100644 coffeelint.json create mode 100644 karma.conf.coffee create mode 100644 test/spec/SettingsSpec.coffee create mode 100644 test/spec/UIUtilSpec.coffee diff --git a/Makefile b/Makefile index e5a84b55c..e95f2e0e9 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,15 @@ NPM = npm -BROWSERIFY = node_modules/.bin/browserify +NODE_BIN_PATH = node_modules/.bin +BROWSERIFY = $(NODE_BIN_PATH)/browserify +COFFEELINT = $(NODE_BIN_PATH)/coffeelint +KARMA = $(NODE_BIN_PATH)/karma GLOBAL_FLAGS = -x jquery -e OUTPUT_DIR = . DEPLOY_DIR = libs -all: compile deploy clean +.PHONY: all compile debug compile-debug app clean deploy test + +all: compile deploy test clean compile:FLAGS = $(GLOBAL_FLAGS) compile: app @@ -22,3 +27,9 @@ clean: deploy: @mkdir -p $(DEPLOY_DIR) && cp $(OUTPUT_DIR)/*.bundle.js $(DEPLOY_DIR) && ./bump-js-versions.sh + +coffeelint: + $(COFFEELINT) *.coffee test/spec/*.coffee + +test: coffeelint + $(KARMA) start karma.conf.coffee \ No newline at end of file diff --git a/coffeelint.json b/coffeelint.json new file mode 100644 index 000000000..15233afe4 --- /dev/null +++ b/coffeelint.json @@ -0,0 +1,129 @@ +{ + "arrow_spacing": { + "level": "ignore" + }, + "braces_spacing": { + "level": "ignore", + "spaces": 0, + "empty_object_spaces": 0 + }, + "camel_case_classes": { + "level": "error" + }, + "coffeescript_error": { + "level": "error" + }, + "colon_assignment_spacing": { + "level": "ignore", + "spacing": { + "left": 0, + "right": 0 + } + }, + "cyclomatic_complexity": { + "value": 10, + "level": "ignore" + }, + "duplicate_key": { + "level": "error" + }, + "empty_constructor_needs_parens": { + "level": "ignore" + }, + "ensure_comprehensions": { + "level": "warn" + }, + "eol_last": { + "level": "ignore" + }, + "indentation": { + "value": 2, + "level": "error" + }, + "line_endings": { + "level": "ignore", + "value": "unix" + }, + "max_line_length": { + "value": 160, + "level": "error", + "limitComments": true + }, + "missing_fat_arrows": { + "level": "ignore", + "is_strict": false + }, + "newlines_after_classes": { + "value": 3, + "level": "ignore" + }, + "no_backticks": { + "level": "error" + }, + "no_debugger": { + "level": "warn", + "console": false + }, + "no_empty_functions": { + "level": "ignore" + }, + "no_empty_param_list": { + "level": "ignore" + }, + "no_implicit_braces": { + "level": "ignore", + "strict": true + }, + "no_implicit_parens": { + "strict": true, + "level": "ignore" + }, + "no_interpolation_in_single_quotes": { + "level": "ignore" + }, + "no_plusplus": { + "level": "ignore" + }, + "no_stand_alone_at": { + "level": "ignore" + }, + "no_tabs": { + "level": "error" + }, + "no_this": { + "level": "ignore" + }, + "no_throwing_strings": { + "level": "error" + }, + "no_trailing_semicolons": { + "level": "error" + }, + "no_trailing_whitespace": { + "level": "error", + "allowed_in_comments": false, + "allowed_in_empty_lines": true + }, + "no_unnecessary_double_quotes": { + "level": "ignore" + }, + "no_unnecessary_fat_arrows": { + "level": "warn" + }, + "non_empty_constructor_needs_parens": { + "level": "ignore" + }, + "prefer_english_operator": { + "level": "ignore", + "doubleNotLevel": "ignore" + }, + "space_operators": { + "level": "ignore" + }, + "spacing_after_comma": { + "level": "ignore" + }, + "transform_messes_up_line_numbers": { + "level": "warn" + } +} diff --git a/karma.conf.coffee b/karma.conf.coffee new file mode 100644 index 000000000..b4148d921 --- /dev/null +++ b/karma.conf.coffee @@ -0,0 +1,49 @@ +module.exports = (config) -> + + config.set + basePath: '' + + frameworks: [ + 'mocha' + 'commonjs' + 'chai-jquery' + 'chai' + 'jquery-2.1.0' + ] + + files: [ + # Modules under test - list specific + './modules/**/Settings.js' + './modules/**/UIUtil.js' + + # Spec files + './test/spec/**/*Spec.coffee' + ] + + exclude: [] + + preprocessors: + # Modules under test + './modules/**/*.js': [ 'commonjs' ] + + # Spec files + './test/spec/**/*Spec.coffee': [ 'coffee', 'commonjs' ] + + commonjsPreprocessor: + shouldExecFile: (file) -> + file.path.indexOf('/spec/') > -1 + processContent: (content, file, cb) -> + cb("'use strict';\n" + content) + + coffeePreprocessor: + options: + bare: true + sourceMap: false + + reporters: [ 'progress' ] + port: 9876 + colors: true + logLevel: config.LOG_INFO + autoWatch: true + browsers: [ 'PhantomJS' ] + singleRun: true diff --git a/libs/app.bundle.js b/libs/app.bundle.js index 3c899d830..68636e507 100644 --- a/libs/app.bundle.js +++ b/libs/app.bundle.js @@ -1,4 +1,4 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.APP=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0 && this._events[type].length > m) { + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + if (typeof console.trace === 'function') { + // not supported in IE 10 + console.trace(); + } + } + } + + return this; +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.once = function(type, listener) { + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + var fired = false; + + function g() { + this.removeListener(type, g); + + if (!fired) { + fired = true; + listener.apply(this, arguments); + } + } + + g.listener = listener; + this.on(type, g); + + return this; +}; + +// emits a 'removeListener' event iff the listener was removed +EventEmitter.prototype.removeListener = function(type, listener) { + var list, position, length, i; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events || !this._events[type]) + return this; + + list = this._events[type]; + length = list.length; + position = -1; + + if (list === listener || + (isFunction(list.listener) && list.listener === listener)) { + delete this._events[type]; + if (this._events.removeListener) + this.emit('removeListener', type, listener); + + } else if (isObject(list)) { + for (i = length; i-- > 0;) { + if (list[i] === listener || + (list[i].listener && list[i].listener === listener)) { + position = i; + break; + } + } + + if (position < 0) + return this; + + if (list.length === 1) { + list.length = 0; + delete this._events[type]; + } else { + list.splice(position, 1); + } + + if (this._events.removeListener) + this.emit('removeListener', type, listener); + } + + return this; +}; + +EventEmitter.prototype.removeAllListeners = function(type) { + var key, listeners; + + if (!this._events) + return this; + + // not listening for removeListener, no need to emit + if (!this._events.removeListener) { + if (arguments.length === 0) + this._events = {}; + else if (this._events[type]) + delete this._events[type]; + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + for (key in this._events) { + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = {}; + return this; + } + + listeners = this._events[type]; + + if (isFunction(listeners)) { + this.removeListener(type, listeners); + } else { + // LIFO order + while (listeners.length) + this.removeListener(type, listeners[listeners.length - 1]); + } + delete this._events[type]; + + return this; +}; + +EventEmitter.prototype.listeners = function(type) { + var ret; + if (!this._events || !this._events[type]) + ret = []; + else if (isFunction(this._events[type])) + ret = [this._events[type]]; + else + ret = this._events[type].slice(); + return ret; +}; + +EventEmitter.listenerCount = function(emitter, type) { + var ret; + if (!emitter._events || !emitter._events[type]) + ret = 0; + else if (isFunction(emitter._events[type])) + ret = 1; + else + ret = emitter._events[type].length; + return ret; +}; + +function isFunction(arg) { + return typeof arg === 'function'; +} + +function isNumber(arg) { + return typeof arg === 'number'; +} + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} + +function isUndefined(arg) { + return arg === void 0; +} + +},{}],67:[function(require,module,exports){ +// shim for using process in browser + +var process = module.exports = {}; +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = setTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + currentQueue[queueIndex].run(); + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + clearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + setTimeout(drainQueue, 0); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +// TODO(shtylman) +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],68:[function(require,module,exports){ // i18next, v1.7.7 // Copyright (c)2014 Jan Mühlemann (jamuhl). // Distributed under MIT license @@ -21332,7 +21727,7 @@ module.exports = XMPP; i18n.options = o; })(); -},{"jquery":"jquery"}],67:[function(require,module,exports){ +},{"jquery":"jquery"}],69:[function(require,module,exports){ // Top level file is just a mixin of submodules & constants 'use strict'; @@ -21347,7 +21742,7 @@ var pako = {}; assign(pako, deflate, inflate, constants); module.exports = pako; -},{"./lib/deflate":68,"./lib/inflate":69,"./lib/utils/common":70,"./lib/zlib/constants":73}],68:[function(require,module,exports){ +},{"./lib/deflate":70,"./lib/inflate":71,"./lib/utils/common":72,"./lib/zlib/constants":75}],70:[function(require,module,exports){ 'use strict'; @@ -21712,7 +22107,7 @@ exports.Deflate = Deflate; exports.deflate = deflate; exports.deflateRaw = deflateRaw; exports.gzip = gzip; -},{"./utils/common":70,"./utils/strings":71,"./zlib/deflate.js":75,"./zlib/messages":80,"./zlib/zstream":82}],69:[function(require,module,exports){ +},{"./utils/common":72,"./utils/strings":73,"./zlib/deflate.js":77,"./zlib/messages":82,"./zlib/zstream":84}],71:[function(require,module,exports){ 'use strict'; @@ -22081,7 +22476,7 @@ exports.inflate = inflate; exports.inflateRaw = inflateRaw; exports.ungzip = inflate; -},{"./utils/common":70,"./utils/strings":71,"./zlib/constants":73,"./zlib/gzheader":76,"./zlib/inflate.js":78,"./zlib/messages":80,"./zlib/zstream":82}],70:[function(require,module,exports){ +},{"./utils/common":72,"./utils/strings":73,"./zlib/constants":75,"./zlib/gzheader":78,"./zlib/inflate.js":80,"./zlib/messages":82,"./zlib/zstream":84}],72:[function(require,module,exports){ 'use strict'; @@ -22184,7 +22579,7 @@ exports.setTyped = function (on) { }; exports.setTyped(TYPED_OK); -},{}],71:[function(require,module,exports){ +},{}],73:[function(require,module,exports){ // String encode/decode helpers 'use strict'; @@ -22371,7 +22766,7 @@ exports.utf8border = function(buf, max) { return (pos + _utf8len[buf[pos]] > max) ? pos : max; }; -},{"./common":70}],72:[function(require,module,exports){ +},{"./common":72}],74:[function(require,module,exports){ 'use strict'; // Note: adler32 takes 12% for level 0 and 2% for level 6. @@ -22404,7 +22799,7 @@ function adler32(adler, buf, len, pos) { module.exports = adler32; -},{}],73:[function(require,module,exports){ +},{}],75:[function(require,module,exports){ module.exports = { /* Allowed flush values; see deflate() and inflate() below for details */ @@ -22452,7 +22847,7 @@ module.exports = { Z_DEFLATED: 8 //Z_NULL: null // Use -1 or null inline, depending on var type }; -},{}],74:[function(require,module,exports){ +},{}],76:[function(require,module,exports){ 'use strict'; // Note: we can't get significant speed boost here. @@ -22494,7 +22889,7 @@ function crc32(crc, buf, len, pos) { module.exports = crc32; -},{}],75:[function(require,module,exports){ +},{}],77:[function(require,module,exports){ 'use strict'; var utils = require('../utils/common'); @@ -24260,7 +24655,7 @@ exports.deflatePending = deflatePending; exports.deflatePrime = deflatePrime; exports.deflateTune = deflateTune; */ -},{"../utils/common":70,"./adler32":72,"./crc32":74,"./messages":80,"./trees":81}],76:[function(require,module,exports){ +},{"../utils/common":72,"./adler32":74,"./crc32":76,"./messages":82,"./trees":83}],78:[function(require,module,exports){ 'use strict'; @@ -24301,7 +24696,7 @@ function GZheader() { } module.exports = GZheader; -},{}],77:[function(require,module,exports){ +},{}],79:[function(require,module,exports){ 'use strict'; // See state defs from inflate.js @@ -24628,7 +25023,7 @@ module.exports = function inflate_fast(strm, start) { return; }; -},{}],78:[function(require,module,exports){ +},{}],80:[function(require,module,exports){ 'use strict'; @@ -26132,7 +26527,7 @@ exports.inflateSync = inflateSync; exports.inflateSyncPoint = inflateSyncPoint; exports.inflateUndermine = inflateUndermine; */ -},{"../utils/common":70,"./adler32":72,"./crc32":74,"./inffast":77,"./inftrees":79}],79:[function(require,module,exports){ +},{"../utils/common":72,"./adler32":74,"./crc32":76,"./inffast":79,"./inftrees":81}],81:[function(require,module,exports){ 'use strict'; @@ -26459,7 +26854,7 @@ module.exports = function inflate_table(type, lens, lens_index, codes, table, ta return 0; }; -},{"../utils/common":70}],80:[function(require,module,exports){ +},{"../utils/common":72}],82:[function(require,module,exports){ 'use strict'; module.exports = { @@ -26473,7 +26868,7 @@ module.exports = { '-5': 'buffer error', /* Z_BUF_ERROR (-5) */ '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */ }; -},{}],81:[function(require,module,exports){ +},{}],83:[function(require,module,exports){ 'use strict'; @@ -27673,7 +28068,7 @@ exports._tr_stored_block = _tr_stored_block; exports._tr_flush_block = _tr_flush_block; exports._tr_tally = _tr_tally; exports._tr_align = _tr_align; -},{"../utils/common":70}],82:[function(require,module,exports){ +},{"../utils/common":72}],84:[function(require,module,exports){ 'use strict'; @@ -27703,9 +28098,9 @@ function ZStream() { } module.exports = ZStream; -},{}],83:[function(require,module,exports){ +},{}],85:[function(require,module,exports){ module.exports = require('./lib/retry'); -},{"./lib/retry":84}],84:[function(require,module,exports){ +},{"./lib/retry":86}],86:[function(require,module,exports){ var RetryOperation = require('./retry_operation'); exports.operation = function(options) { @@ -27756,7 +28151,7 @@ exports._createTimeout = function(attempt, opts) { return timeout; }; -},{"./retry_operation":85}],85:[function(require,module,exports){ +},{"./retry_operation":87}],87:[function(require,module,exports){ function RetryOperation(timeouts) { this._timeouts = timeouts; this._fn = null; @@ -27866,7 +28261,7 @@ RetryOperation.prototype.mainError = function() { return mainError; }; -},{}],86:[function(require,module,exports){ +},{}],88:[function(require,module,exports){ module.exports = function arrayEquals(array) { // if the other array is a falsy value, return if (!array) @@ -27892,10 +28287,10 @@ module.exports = function arrayEquals(array) { } -},{}],87:[function(require,module,exports){ +},{}],89:[function(require,module,exports){ exports.Interop = require('./interop'); -},{"./interop":88}],88:[function(require,module,exports){ +},{"./interop":90}],90:[function(require,module,exports){ "use strict"; var transform = require('./transform'); @@ -28477,7 +28872,7 @@ Interop.prototype.toUnifiedPlan = function(desc) { //#endregion }; -},{"./array-equals":86,"./transform":89}],89:[function(require,module,exports){ +},{"./array-equals":88,"./transform":91}],91:[function(require,module,exports){ var transform = require('sdp-transform'); exports.write = function(session, opts) { @@ -28576,7 +28971,7 @@ exports.parse = function(sdp) { }; -},{"sdp-transform":91}],90:[function(require,module,exports){ +},{"sdp-transform":93}],92:[function(require,module,exports){ var grammar = module.exports = { v: [{ name: 'version', @@ -28825,7 +29220,7 @@ Object.keys(grammar).forEach(function (key) { }); }); -},{}],91:[function(require,module,exports){ +},{}],93:[function(require,module,exports){ var parser = require('./parser'); var writer = require('./writer'); @@ -28835,7 +29230,7 @@ exports.parseFmtpConfig = parser.parseFmtpConfig; exports.parsePayloads = parser.parsePayloads; exports.parseRemoteCandidates = parser.parseRemoteCandidates; -},{"./parser":92,"./writer":93}],92:[function(require,module,exports){ +},{"./parser":94,"./writer":95}],94:[function(require,module,exports){ var toIntIfInt = function (v) { return String(Number(v)) === v ? Number(v) : v; }; @@ -28930,7 +29325,7 @@ exports.parseRemoteCandidates = function (str) { return candidates; }; -},{"./grammar":90}],93:[function(require,module,exports){ +},{"./grammar":92}],95:[function(require,module,exports){ var grammar = require('./grammar'); // customized util.format - discards excess arguments and can void middle ones @@ -29046,14 +29441,14 @@ module.exports = function (session, opts) { return sdp.join('\r\n') + '\r\n'; }; -},{"./grammar":90}],94:[function(require,module,exports){ +},{"./grammar":92}],96:[function(require,module,exports){ var MediaStreamType = { VIDEO_TYPE: "Video", AUDIO_TYPE: "Audio" }; module.exports = MediaStreamType; -},{}],95:[function(require,module,exports){ +},{}],97:[function(require,module,exports){ var RTCBrowserType = { RTC_BROWSER_CHROME: "rtc_browser.chrome", @@ -29061,7 +29456,7 @@ var RTCBrowserType = { }; module.exports = RTCBrowserType; -},{}],96:[function(require,module,exports){ +},{}],98:[function(require,module,exports){ var RTCEvents = { LASTN_CHANGED: "rtc.lastn_changed", DOMINANTSPEAKER_CHANGED: "rtc.dominantspeaker_changed", @@ -29074,7 +29469,7 @@ var RTCEvents = { }; module.exports = RTCEvents; -},{}],97:[function(require,module,exports){ +},{}],99:[function(require,module,exports){ var Resolutions = { "1080": { width: 1920, @@ -29128,7 +29523,7 @@ var Resolutions = { } }; module.exports = Resolutions; -},{}],98:[function(require,module,exports){ +},{}],100:[function(require,module,exports){ var StreamEventTypes = { EVENT_TYPE_LOCAL_CREATED: "stream.local_created", @@ -29144,14 +29539,14 @@ var StreamEventTypes = { }; module.exports = StreamEventTypes; -},{}],99:[function(require,module,exports){ +},{}],101:[function(require,module,exports){ var UIEvents = { NICKNAME_CHANGED: "UI.nickname_changed", SELECTED_ENDPOINT: "UI.selected_endpoint", PINNED_ENDPOINT: "UI.pinned_endpoint" }; module.exports = UIEvents; -},{}],100:[function(require,module,exports){ +},{}],102:[function(require,module,exports){ var AuthenticationEvents = { /** * Event callback arguments: @@ -29165,7 +29560,7 @@ var AuthenticationEvents = { }; module.exports = AuthenticationEvents; -},{}],101:[function(require,module,exports){ +},{}],103:[function(require,module,exports){ var CQEvents = { LOCALSTATS_UPDATED: "cq.localstats_updated", REMOTESTATS_UPDATED: "cq.remotestats_updated", @@ -29173,7 +29568,7 @@ var CQEvents = { }; module.exports = CQEvents; -},{}],102:[function(require,module,exports){ +},{}],104:[function(require,module,exports){ var DesktopSharingEventTypes = { INIT: "ds.init", @@ -29183,14 +29578,14 @@ var DesktopSharingEventTypes = { }; module.exports = DesktopSharingEventTypes; -},{}],103:[function(require,module,exports){ +},{}],105:[function(require,module,exports){ var Events = { DTMF_SUPPORT_CHANGED: "members.dtmf_support_changed" }; module.exports = Events; -},{}],104:[function(require,module,exports){ +},{}],106:[function(require,module,exports){ module.exports = { getLanguages : function () { var languages = []; @@ -29207,7 +29602,7 @@ module.exports = { TR: "tr", FR: "fr" } -},{}],105:[function(require,module,exports){ +},{}],107:[function(require,module,exports){ var XMPPEvents = { CONNECTION_FAILED: "xmpp.connection.failed", CONFERENCE_CREATED: "xmpp.conferenceCreated.jingle", @@ -29243,367 +29638,5 @@ var XMPPEvents = { START_MUTED: "xmpp.start_muted" }; module.exports = XMPPEvents; -},{}],106:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -function EventEmitter() { - this._events = this._events || {}; - this._maxListeners = this._maxListeners || undefined; -} -module.exports = EventEmitter; - -// Backwards-compat with node 0.10.x -EventEmitter.EventEmitter = EventEmitter; - -EventEmitter.prototype._events = undefined; -EventEmitter.prototype._maxListeners = undefined; - -// By default EventEmitters will print a warning if more than 10 listeners are -// added to it. This is a useful default which helps finding memory leaks. -EventEmitter.defaultMaxListeners = 10; - -// Obviously not all Emitters should be limited to 10. This function allows -// that to be increased. Set to zero for unlimited. -EventEmitter.prototype.setMaxListeners = function(n) { - if (!isNumber(n) || n < 0 || isNaN(n)) - throw TypeError('n must be a positive number'); - this._maxListeners = n; - return this; -}; - -EventEmitter.prototype.emit = function(type) { - var er, handler, len, args, i, listeners; - - if (!this._events) - this._events = {}; - - // If there is no 'error' event listener then throw. - if (type === 'error') { - if (!this._events.error || - (isObject(this._events.error) && !this._events.error.length)) { - er = arguments[1]; - if (er instanceof Error) { - throw er; // Unhandled 'error' event - } - throw TypeError('Uncaught, unspecified "error" event.'); - } - } - - handler = this._events[type]; - - if (isUndefined(handler)) - return false; - - if (isFunction(handler)) { - switch (arguments.length) { - // fast cases - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - // slower - default: - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - handler.apply(this, args); - } - } else if (isObject(handler)) { - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - - listeners = handler.slice(); - len = listeners.length; - for (i = 0; i < len; i++) - listeners[i].apply(this, args); - } - - return true; -}; - -EventEmitter.prototype.addListener = function(type, listener) { - var m; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events) - this._events = {}; - - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (this._events.newListener) - this.emit('newListener', type, - isFunction(listener.listener) ? - listener.listener : listener); - - if (!this._events[type]) - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - else if (isObject(this._events[type])) - // If we've already got an array, just append. - this._events[type].push(listener); - else - // Adding the second element, need to change to array. - this._events[type] = [this._events[type], listener]; - - // Check for listener leak - if (isObject(this._events[type]) && !this._events[type].warned) { - var m; - if (!isUndefined(this._maxListeners)) { - m = this._maxListeners; - } else { - m = EventEmitter.defaultMaxListeners; - } - - if (m && m > 0 && this._events[type].length > m) { - this._events[type].warned = true; - console.error('(node) warning: possible EventEmitter memory ' + - 'leak detected. %d listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.', - this._events[type].length); - if (typeof console.trace === 'function') { - // not supported in IE 10 - console.trace(); - } - } - } - - return this; -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.once = function(type, listener) { - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - var fired = false; - - function g() { - this.removeListener(type, g); - - if (!fired) { - fired = true; - listener.apply(this, arguments); - } - } - - g.listener = listener; - this.on(type, g); - - return this; -}; - -// emits a 'removeListener' event iff the listener was removed -EventEmitter.prototype.removeListener = function(type, listener) { - var list, position, length, i; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events || !this._events[type]) - return this; - - list = this._events[type]; - length = list.length; - position = -1; - - if (list === listener || - (isFunction(list.listener) && list.listener === listener)) { - delete this._events[type]; - if (this._events.removeListener) - this.emit('removeListener', type, listener); - - } else if (isObject(list)) { - for (i = length; i-- > 0;) { - if (list[i] === listener || - (list[i].listener && list[i].listener === listener)) { - position = i; - break; - } - } - - if (position < 0) - return this; - - if (list.length === 1) { - list.length = 0; - delete this._events[type]; - } else { - list.splice(position, 1); - } - - if (this._events.removeListener) - this.emit('removeListener', type, listener); - } - - return this; -}; - -EventEmitter.prototype.removeAllListeners = function(type) { - var key, listeners; - - if (!this._events) - return this; - - // not listening for removeListener, no need to emit - if (!this._events.removeListener) { - if (arguments.length === 0) - this._events = {}; - else if (this._events[type]) - delete this._events[type]; - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - for (key in this._events) { - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = {}; - return this; - } - - listeners = this._events[type]; - - if (isFunction(listeners)) { - this.removeListener(type, listeners); - } else { - // LIFO order - while (listeners.length) - this.removeListener(type, listeners[listeners.length - 1]); - } - delete this._events[type]; - - return this; -}; - -EventEmitter.prototype.listeners = function(type) { - var ret; - if (!this._events || !this._events[type]) - ret = []; - else if (isFunction(this._events[type])) - ret = [this._events[type]]; - else - ret = this._events[type].slice(); - return ret; -}; - -EventEmitter.listenerCount = function(emitter, type) { - var ret; - if (!emitter._events || !emitter._events[type]) - ret = 0; - else if (isFunction(emitter._events[type])) - ret = 1; - else - ret = emitter._events[type].length; - return ret; -}; - -function isFunction(arg) { - return typeof arg === 'function'; -} - -function isNumber(arg) { - return typeof arg === 'number'; -} - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} - -function isUndefined(arg) { - return arg === void 0; -} - -},{}],107:[function(require,module,exports){ -// shim for using process in browser - -var process = module.exports = {}; -var queue = []; -var draining = false; - -function drainQueue() { - if (draining) { - return; - } - draining = true; - var currentQueue; - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - var i = -1; - while (++i < len) { - currentQueue[i](); - } - len = queue.length; - } - draining = false; -} -process.nextTick = function (fun) { - queue.push(fun); - if (!draining) { - setTimeout(drainQueue, 0); - } -}; - -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; - -// TODO(shtylman) -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; - },{}]},{},[1])(1) }); \ No newline at end of file diff --git a/package.json b/package.json index 010d76a17..d5a3f84ed 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "browser" ], "scripts": { - "test": "make compile" + "test": "make" }, "author": "", "readmeFilename": "README.md", @@ -27,7 +27,22 @@ "retry": "0.6.1" }, "devDependencies": { - "browserify": "^10.2.3" + "browserify": "^10.2.3", + "chai": "^3.0.0", + "chai-jquery": "^2.0.0", + "coffee-script": "^1.9.3", + "coffeelint": "^1.10.1", + "jquery": "^2.1.4", + "karma": "^0.12.36", + "karma-chai": "^0.1.0", + "karma-chai-jquery": "^1.0.0", + "karma-coffee-preprocessor": "^0.2.1", + "karma-commonjs-plus": "^1.0.0", + "karma-jquery": "^0.1.0", + "karma-mocha": "^0.1.10", + "karma-phantomjs-launcher": "^0.2.0", + "mocha": "^2.2.5", + "phantomjs": "^1.9.17" }, "license": "MIT" } diff --git a/test/spec/SettingsSpec.coffee b/test/spec/SettingsSpec.coffee new file mode 100644 index 000000000..729c74835 --- /dev/null +++ b/test/spec/SettingsSpec.coffee @@ -0,0 +1,64 @@ +'use strict' + +describe 'Settings', -> + Settings = require('../../modules/settings/Settings') + generated_uid = window.localStorage.jitsiMeetId + + afterEach -> + window.localStorage.clear() + + it 'should initialize correctly', -> + settings = Settings.getSettings() + assert.propertyVal settings, 'displayName', '' + assert.propertyVal settings, 'email', '' + assert.propertyVal settings, 'language', undefined + assert.propertyVal settings, 'uid', generated_uid + + describe '#setDisplayName(displayName)', -> + + it 'should be able to set global display name', -> + Settings.setDisplayName('My Name') + assert.propertyVal Settings.getSettings(), 'displayName', 'My Name' + + it 'should set localStorage displayname', -> + Settings.setDisplayName('My Name') + assert.equal window.localStorage.displayname, 'My Name' + + describe '#setEmail(email)', -> + + it 'should be able to set a global email address', -> + Settings.setEmail 'my@email.com' + assert.propertyVal Settings.getSettings(), 'email', 'my@email.com' + + it 'should set localStorage email', -> + Settings.setEmail 'my@email.com' + assert.equal window.localStorage.email, 'my@email.com' + + describe '#setLanguage(language)', -> + + it 'should be able to get set global language', -> + Settings.setLanguage 'Russian' + assert.propertyVal Settings.getSettings(), 'language', 'Russian' + + it 'should set localStorage language', -> + Settings.setLanguage 'Russian' + assert.equal window.localStorage.language, 'Russian' + + describe '#getSettings()', -> + + before -> + Settings.setDisplayName 'foo' + Settings.setEmail 'foo@bar' + Settings.setLanguage 'Luxembourgish' + + it 'should be able to get displayName', -> + assert.propertyVal Settings.getSettings(), 'displayName', 'foo' + + it 'should be able to get email', -> + assert.propertyVal Settings.getSettings(), 'email', 'foo@bar' + + it 'should be able to get language', -> + assert.propertyVal Settings.getSettings(), 'language', 'Luxembourgish' + + it 'should be able to get uid', -> + assert.propertyVal Settings.getSettings(), 'uid', generated_uid diff --git a/test/spec/UIUtilSpec.coffee b/test/spec/UIUtilSpec.coffee new file mode 100644 index 000000000..ebc066ce3 --- /dev/null +++ b/test/spec/UIUtilSpec.coffee @@ -0,0 +1,16 @@ +'use strict' + +describe 'UIUtilSpec', -> + UIUtil = require('../../modules/UI/util/UIUtil') + + describe '#buttonClick(id, classname)', -> + + it 'should add the class to the clicked element', -> + document.body.innerHTML = '
test
' + UIUtil.buttonClick('#test', "hidden") + $('#test').should.have.class('hidden') + + it 'should remove the class to the clicked element', -> + document.body.innerHTML = '' + UIUtil.buttonClick('#test', "hidden") + $('#test').should.not.have.class('hidden')