From f54cde985b224182a63376bd5d152bf68799917e Mon Sep 17 00:00:00 2001 From: Lawrence Carvalho Date: Sat, 18 Aug 2012 11:45:31 +0100 Subject: [PATCH 1/2] Moved tests to mocha/chai and removed travis-ci jasmine spec runner in favour of phantomjs --- .gitmodules | 9 +- .travis.yml | 13 +- Gemfile | 6 - README.md | 15 +- Rakefile | 51 -- config.ru | 5 - lib/chai | 1 + lib/jasmine | 1 - lib/mocha | 1 + lib/test-helpers/bind.js | 26 + lib/test-helpers/console.js | 577 +++++++++++++++++++++ lib/test-helpers/process-std-out-write.js | 29 ++ lib/test-helpers/run-mocha.js | 86 +++ lib/test-helpers/run_jasmine_test.coffee | 48 -- spec/javascripts/support/jasmine.yml | 76 --- spec/javascripts/support/jasmine_config.rb | 23 - spec/javascripts/support/jasmine_runner.rb | 32 -- src/tests/aspectos.js | 18 +- src/tests/index.html | 40 +- 19 files changed, 782 insertions(+), 275 deletions(-) delete mode 100644 Gemfile delete mode 100644 Rakefile delete mode 100644 config.ru create mode 160000 lib/chai delete mode 160000 lib/jasmine create mode 160000 lib/mocha create mode 100644 lib/test-helpers/bind.js create mode 100644 lib/test-helpers/console.js create mode 100644 lib/test-helpers/process-std-out-write.js create mode 100644 lib/test-helpers/run-mocha.js delete mode 100644 lib/test-helpers/run_jasmine_test.coffee delete mode 100644 spec/javascripts/support/jasmine.yml delete mode 100644 spec/javascripts/support/jasmine_config.rb delete mode 100644 spec/javascripts/support/jasmine_runner.rb diff --git a/.gitmodules b/.gitmodules index 1af7b16..8f59271 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,9 @@ -[submodule "lib/jasmine"] - path = lib/jasmine - url = https://github.com/pivotal/jasmine.git [submodule "lib/ender"] path = lib/ender url = https://github.com/ender-js/Ender.git +[submodule "lib/mocha"] + path = lib/mocha + url = git://github.com/visionmedia/mocha.git +[submodule "lib/chai"] + path = lib/chai + url = git://github.com/chaijs/chai.git diff --git a/.travis.yml b/.travis.yml index 552ee34..32e1cae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,7 @@ +language: ruby rvm: - 1.9.3 -bundler_args: --without development -before_script: - - "git submodule update --init" - - "export DISPLAY=:99.0" - - "sh -e /etc/init.d/xvfb start" - - bundle exec rackup & - - sleep 5 -script: phantomjs ./lib/test-helpers/run_jasmine_test.coffee "http://localhost:9292/src/tests/index.html" \ No newline at end of file +notifications: + email: false +script: + - "phantomjs ./lib/test-helpers/run-mocha.js file://localhost/$(pwd)/src/tests/index.html#ci" \ No newline at end of file diff --git a/Gemfile b/Gemfile deleted file mode 100644 index 4c350d4..0000000 --- a/Gemfile +++ /dev/null @@ -1,6 +0,0 @@ -source :rubygems - -gem 'jasmine' -gem 'rake' -gem 'json' -gem 'selenium-webdriver', '>= 2.13.0' \ No newline at end of file diff --git a/README.md b/README.md index 51b7a72..4b82a98 100644 --- a/README.md +++ b/README.md @@ -76,4 +76,17 @@ Aspectos provides three methods to provide the basic aspects to your objects: ## Tests -See the index.html file in the tests directory \ No newline at end of file +See the index.html file in the tests directory + +If you have testem installed run it from the root directory of the repo. + + testem + +or + + + testem ci -b Chrome + +Mocha tests can be run with phantomjs (note the ci hash parameter): + + phantomjs ./lib/test-helpers/run-mocha.js file://localhost/$(pwd)/aspectos/src/tests/index.html#ci \ No newline at end of file diff --git a/Rakefile b/Rakefile deleted file mode 100644 index 1ff98c3..0000000 --- a/Rakefile +++ /dev/null @@ -1,51 +0,0 @@ -namespace :jasmine do - task :ci do - require 'jasmine' - load 'jasmine/tasks/jasmine.rake' - ### rescue LoadError - ### task :jasmine do - ### abort "Jasmine is not available. In order to run jasmine, you must: (sudo) gem install jasmine" - ### end - end -end - -namespace :jshint do - task :require do - sh "which jshint" do |ok, res| - fail 'Cannot find jshint on $PATH' unless ok - end - end - - task :check => 'jshint:require' do - project_root = File.expand_path('', File.dirname(__FILE__)) - ### config_file = File.join(project_root, 'config', 'jshint.json') - js_root_dir = File.join(project_root, 'src') - - files = Rake::FileList.new - files.include File.join(js_root_dir, '**', '*.js') - files.exclude File.join(js_root_dir, 'lib', '**', '*.js') - print js_root_dir - print js_root_dir - ###sh "jshint #{files.join(' ')} --config #{config_file}" do |ok, res| - sh "jshint #{files.join(' ')}" do |ok, res| - fail 'JSHint found errors.' unless ok - end - end -end - -desc 'Run JSHint checks against Javascript source' -task :jshint => 'jshint:check' - -task :travis do - ["rake jasmine:ci"].each do |cmd| - puts "Starting to run #{cmd}..." - system("export DISPLAY=:99.0 && bundle exec #{cmd}") - raise "#{cmd} failed!" unless $?.exitstatus == 0 - end -end - -desc "none" -task :none do -end - -task :default => 'none' \ No newline at end of file diff --git a/config.ru b/config.ru deleted file mode 100644 index 78543dd..0000000 --- a/config.ru +++ /dev/null @@ -1,5 +0,0 @@ -require 'webrick' -server = WEBrick::HTTPServer.new :Port => 9292 -server.mount "/", WEBrick::HTTPServlet::FileHandler, './' -trap('INT') { server.stop } -server.start \ No newline at end of file diff --git a/lib/chai b/lib/chai new file mode 160000 index 0000000..35bec1b --- /dev/null +++ b/lib/chai @@ -0,0 +1 @@ +Subproject commit 35bec1b89603c679a6cf6f28e685bc552ad6a1e8 diff --git a/lib/jasmine b/lib/jasmine deleted file mode 160000 index 06c900a..0000000 --- a/lib/jasmine +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 06c900ab20efbf10233ba2e52521a14ac2af23c5 diff --git a/lib/mocha b/lib/mocha new file mode 160000 index 0000000..eb73c7f --- /dev/null +++ b/lib/mocha @@ -0,0 +1 @@ +Subproject commit eb73c7f16d5c823a2f5427cac707e4ad0bf9ab5b diff --git a/lib/test-helpers/bind.js b/lib/test-helpers/bind.js new file mode 100644 index 0000000..fb16ed8 --- /dev/null +++ b/lib/test-helpers/bind.js @@ -0,0 +1,26 @@ +/* + A shim for non ES5 supporting browsers (phantomjs). + Adds function bind to Function prototype, so that you can do partial application. + Works even with the nasty thing, where the first word is the opposite of extranet, the second one is the profession of Columbus, and the version number is 9, flipped 180 degrees. +*/ + +Function.prototype.bind = Function.prototype.bind || function(to){ + // Make an array of our arguments, starting from second argument + var partial = Array.prototype.splice.call(arguments, 1), + // We'll need the original function. + fn = this; + var bound = function (){ + // Join the already applied arguments to the now called ones (after converting to an array again). + var args = partial.concat(Array.prototype.splice.call(arguments, 0)); + // If not being called as a constructor + if (!(this instanceof bound)){ + // return the result of the function called bound to target and partially applied. + return fn.apply(to, args); + } + // If being called as a constructor, apply the function bound to self. + fn.apply(this, args); + } + // Attach the prototype of the function to our newly created function. + bound.prototype = fn.prototype; + return bound; +}; diff --git a/lib/test-helpers/console.js b/lib/test-helpers/console.js new file mode 100644 index 0000000..ee972e0 --- /dev/null +++ b/lib/test-helpers/console.js @@ -0,0 +1,577 @@ +/* +* In phantomjs, console.log do not support formatting. +* +* Unfortunately, Mocha need formatting, so I monkey-patched +* console.log in order to apply +* before outputting. +* +* */ +(function(){ + + var 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. + + var formatRegExp = /%[sdj%]/g; + exports.format = function(f) { + if (typeof f !== 'string') { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); + } + return objects.join(' '); + } + + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%%') return '%'; + if (i >= len) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': return JSON.stringify(args[i++]); + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (x === null || typeof x !== 'object') { + str += ' ' + x; + } else { + str += ' ' + inspect(x); + } + } + return str; + }; + + + // Mark that a method should not be used. + // Returns a modified function which warns once by default. + // If --no-deprecation is set, then it is a no-op. + exports.deprecate = function(fn, msg) { + + var warned = false; + function deprecated() { + if (!warned) { + console.trace(msg); + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; + }; + + + exports.print = function() { + for (var i = 0, len = arguments.length; i < len; ++i) { + process.stdout.write(String(arguments[i])); + } + }; + + + exports.puts = function() { + for (var i = 0, len = arguments.length; i < len; ++i) { + process.stdout.write(arguments[i] + '\n'); + } + }; + + + exports.debug = function(x) { + process.stderr.write('DEBUG: ' + x + '\n'); + }; + + + var error = exports.error = function(x) { + for (var i = 0, len = arguments.length; i < len; ++i) { + process.stderr.write(arguments[i] + '\n'); + } + }; + + + /** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Boolean} showHidden Flag that shows hidden (not enumerable) + * properties of objects. + * @param {Number} depth Depth in which to descend in object. Default is 2. + * @param {Boolean} colors Flag to turn on ANSI escape codes to color the + * output. Default is false (no coloring). + */ + function inspect(obj, showHidden, depth, colors) { + var ctx = { + showHidden: showHidden, + seen: [], + stylize: colors ? stylizeWithColor : stylizeNoColor + }; + return formatValue(ctx, obj, (typeof depth === 'undefined' ? 2 : depth)); + } + exports.inspect = inspect; + + + // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics + var colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] + }; + + // Don't use 'blue' not visible on cmd.exe + var styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' + }; + + + function stylizeWithColor(str, styleType) { + var style = styles[styleType]; + + if (style) { + return '\033[' + colors[style][0] + 'm' + str + + '\033[' + colors[style][1] + 'm'; + } else { + return str; + } + } + + + function stylizeNoColor(str, styleType) { + return str; + } + + + function arrayToHash(array) { + var hash = {}; + + array.forEach(function(val, idx) { + hash[val] = true; + }); + + return hash; + } + + + function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (value && typeof value.inspect === 'function' && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + return String(value.inspect(recurseTimes)); + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // Look up the keys of the object. + var keys = Object.keys(value); + var visibleKeys = arrayToHash(keys); + + if (ctx.showHidden) { + keys = Object.getOwnPropertyNames(value); + } + + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (typeof value === 'function') { + var name = value.name ? ': ' + value.name : ''; + return ctx.stylize('[Function' + name + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (typeof value === 'function') { + var n = value.name ? ': ' + value.name : ''; + base = ' [Function' + n + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); + } + + + function formatPrimitive(ctx, value) { + switch (typeof value) { + case 'undefined': + return ctx.stylize('undefined', 'undefined'); + + case 'string': + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + + case 'number': + return ctx.stylize('' + value, 'number'); + + case 'boolean': + return ctx.stylize('' + value, 'boolean'); + } + // For some reason typeof null is "object", so special case here. + if (value === null) { + return ctx.stylize('null', 'null'); + } + } + + + function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; + } + + + function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (Object.prototype.hasOwnProperty.call(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; + } + + + function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc; + desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special'); + } + } + if (!visibleKeys.hasOwnProperty(key)) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(desc.value) < 0) { + if (recurseTimes === null) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (typeof name === 'undefined') { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; + } + + + function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = output.reduce(function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; + } + + + // NOTE: These type checking functions intentionally don't use `instanceof` + // because it is fragile and can be easily faked with `Object.create()`. + function isArray(ar) { + return Array.isArray(ar) || + (typeof ar === 'object' && objectToString(ar) === '[object Array]'); + } + exports.isArray = isArray; + + + function isRegExp(re) { + return typeof re === 'object' && objectToString(re) === '[object RegExp]'; + } + exports.isRegExp = isRegExp; + + + function isDate(d) { + return typeof d === 'object' && objectToString(d) === '[object Date]'; + } + exports.isDate = isDate; + + + function isError(e) { + return typeof e === 'object' && objectToString(e) === '[object Error]'; + } + exports.isError = isError; + + + function objectToString(o) { + return Object.prototype.toString.call(o); + } + + + exports.p = exports.deprecate(function() { + for (var i = 0, len = arguments.length; i < len; ++i) { + error(exports.inspect(arguments[i])); + } + }, 'util.p: Use console.error() instead.'); + + + function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); + } + + + var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec']; + + // 26 Feb 16:19:34 + function timestamp() { + var d = new Date(); + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':'); + return [d.getDate(), months[d.getMonth()], time].join(' '); + } + + + exports.log = function(msg) { + exports.puts(timestamp() + ' - ' + msg.toString()); + }; + + + exports.exec = exports.deprecate(function() { + return require('child_process').exec.apply(this, arguments); + }, 'util.exec is now called `child_process.exec`.'); + + + exports.pump = function(readStream, writeStream, callback) { + var callbackCalled = false; + + function call(a, b, c) { + if (callback && !callbackCalled) { + callback(a, b, c); + callbackCalled = true; + } + } + + readStream.addListener('data', function(chunk) { + if (writeStream.write(chunk) === false) readStream.pause(); + }); + + writeStream.addListener('drain', function() { + readStream.resume(); + }); + + readStream.addListener('end', function() { + writeStream.end(); + }); + + readStream.addListener('close', function() { + call(); + }); + + readStream.addListener('error', function(err) { + writeStream.end(); + call(err); + }); + + writeStream.addListener('error', function(err) { + readStream.destroy(); + call(err); + }); + }; + + + /** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ + exports.inherits = function(ctor, superCtor) { + ctor.super_ = superCtor; + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; + + exports._extend = function(origin, add) { + // Don't do anything if add isn't an object + if (!add || typeof add !== 'object') return origin; + + var keys = Object.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; + } + return origin; + }; + + + /* Now override console.log */ + var _log = console.log; + var _error = console.error; + + console.log = function(){ + _log.call(console, exports.format.apply(this, arguments)); + }; + + console.error = function(){ + _error.call(console, exports.format.apply(this, arguments)); + }; + +})(); \ No newline at end of file diff --git a/lib/test-helpers/process-std-out-write.js b/lib/test-helpers/process-std-out-write.js new file mode 100644 index 0000000..b6b7c89 --- /dev/null +++ b/lib/test-helpers/process-std-out-write.js @@ -0,0 +1,29 @@ +/* +* Mocha need process.stdout.write in order to change the cursor position, +* So I implemented a dummy `process.stdout.write` that debouce a `console.log` +* and enqueue the logs to print. +* */ +(function(){ + process.stdout.write = debouceAndAppend(function(){ console.log.apply(console, arguments); }, 300); + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. + // + // the first argument (a string) is appended each time debouceAndAppend is called. + function debouceAndAppend(func, wait) { + var timeout, firstArg = ''; + return function() { + var context = this, args = arguments; + firstArg = firstArg + arguments[0].toString(); + var later = function() { + timeout = null; + args[0] = firstArg; + func.apply(context, args); + firstArg = ''; + }; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + }; + } +})(); \ No newline at end of file diff --git a/lib/test-helpers/run-mocha.js b/lib/test-helpers/run-mocha.js new file mode 100644 index 0000000..ce2c6e0 --- /dev/null +++ b/lib/test-helpers/run-mocha.js @@ -0,0 +1,86 @@ +/*global phantom:true, console:true, WebPage:true, Date:true*/ +(function () { + var url, timeout, page, defer; + + if (phantom.args.length < 1) { + console.log("Usage: phantomjs run-mocha.js URL [timeout]"); + phantom.exit(); + } + + url = phantom.args[0]; + timeout = phantom.args[1] || 6000; + + page = new WebPage(); + + defer = function (test) { + var start, condition, func, interval, time, testStart; + start = new Date().getTime(); + testStart = new Date().getTime(); + condition = false; + func = function () { + if (new Date().getTime() - start < timeout && !condition) { + condition = test(); + } else { + if (!condition) { + console.log("Timeout passed before the tests finished."); + phantom.exit(1); + } else { + clearInterval(interval); + phantom.exit(0); + } + } + }; + interval = setInterval(func, 100); + }; + page.onConsoleMessage = function (msg) { console.log(msg); }; + page.open(url, function (status) { + var test; + // inject custom scripts to change the behaviour of phantomjs + + // add ES5 bind + page.injectJs('bind.js'); +// +// // add the node.js console + page.injectJs('console.js'); +// +// // add a shim for the node.js process.stdout.write + page.injectJs('process-std-out-write.js'); + + // now execute phantomjs + page.evaluate(function(){ + + // setup mocha with the [spec reporter](http://visionmedia.github.com/mocha/#spec-reporter) + mocha.setup({ + ui: 'bdd', + + // TODO: it could be great to pass `spec` has an option in the command line. + // + reporter: mocha.reporters.Spec + }); + + + // wait for dom loaded + $.domReady(function(){ + // then run mocha + mocha.run().on('end', function(){ + // and add a flag when the test end. + mocha.end = true; + }); + }); + }); + if (status !== "success") { + console.log("Failed to load the page. Check the url"); + phantom.exit(1); + } + + // to know if mocha has finished running or not. + test = function () { + return page.evaluate(function () { + // custom flag, set ~10 lines before + return mocha.end; + }); + }; + defer(test); + }); + +}()); \ No newline at end of file diff --git a/lib/test-helpers/run_jasmine_test.coffee b/lib/test-helpers/run_jasmine_test.coffee deleted file mode 100644 index 5e458ab..0000000 --- a/lib/test-helpers/run_jasmine_test.coffee +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/local/bin/phantomjs - -# Runs a Jasmine Suite from an html page -# @page is a PhantomJs page object -# @exit_func is the function to call in order to exit the script - -class PhantomJasmineRunner - constructor: (@page, @exit_func = phantom.exit) -> - @tries = 0 - @max_tries = 10 - - init: -> - setTimeout (=> - @inc_tries() - @exit_if_jasmine_done() - ), 100 - - get_status: -> @page.evaluate(-> console_reporter.status) - - exit_if_jasmine_done: -> - switch @get_status() - when "success" then @exit_func 0 - when "fail" then @exit_func 1 - else - - inc_tries: -> - @tries += 1 - @exit_func 1 if @tries > @max_tries - -# Script Begin -if phantom.args.length == 0 - console.log "Need a url as the argument" - phantom.exit 1 - -page = new WebPage() -# Don't supress console output -page.onConsoleMessage = (msg) -> console.log msg - -address = phantom.args[0] - -page.open address, (status) -> - if status != "success" - console.log "can't load the address!" - phantom.exit 1 - - runner = new PhantomJasmineRunner(page) - runner.init() - diff --git a/spec/javascripts/support/jasmine.yml b/spec/javascripts/support/jasmine.yml deleted file mode 100644 index cdaba92..0000000 --- a/spec/javascripts/support/jasmine.yml +++ /dev/null @@ -1,76 +0,0 @@ -# src_files -# -# Return an array of filepaths relative to src_dir to include before jasmine specs. -# Default: [] -# -# EXAMPLE: -# -# src_files: -# - lib/source1.js -# - lib/source2.js -# - dist/**/*.js -# -src_files: - - lib/ender.js - - src/aspectos.js - -# stylesheets -# -# Return an array of stylesheet filepaths relative to src_dir to include before jasmine specs. -# Default: [] -# -# EXAMPLE: -# -# stylesheets: -# - css/style.css -# - stylesheets/*.css -# -stylesheets: - -# helpers -# -# Return an array of filepaths relative to spec_dir to include before jasmine specs. -# Default: ["helpers/**/*.js"] -# -# EXAMPLE: -# -# helpers: -# - helpers/**/*.js -# -helpers: - -# spec_files -# -# Return an array of filepaths relative to spec_dir to include. -# Default: ["**/*[sS]pec.js"] -# -# EXAMPLE: -# -# spec_files: -# - **/*[sS]pec.js -# -spec_files: - - aspectos.js - -# src_dir -# -# Source directory path. Your src_files must be returned relative to this path. Will use root if left blank. -# Default: project root -# -# EXAMPLE: -# -# src_dir: public -# -src_dir: - -# spec_dir -# -# Spec directory path. Your spec_files must be returned relative to this path. -# Default: spec/javascripts -# -# EXAMPLE: -# -# spec_dir: spec/javascripts -# -spec_dir: - - src/tests diff --git a/spec/javascripts/support/jasmine_config.rb b/spec/javascripts/support/jasmine_config.rb deleted file mode 100644 index 47286f2..0000000 --- a/spec/javascripts/support/jasmine_config.rb +++ /dev/null @@ -1,23 +0,0 @@ -module Jasmine - class Config - - # Add your overrides or custom config code here - - end -end - - -# Note - this is necessary for rspec2, which has removed the backtrace -module Jasmine - class SpecBuilder - def declare_spec(parent, spec) - me = self - example_name = spec["name"] - @spec_ids << spec["id"] - backtrace = @example_locations[parent.description + " " + example_name] - parent.it example_name, {} do - me.report_spec(spec["id"]) - end - end - end -end diff --git a/spec/javascripts/support/jasmine_runner.rb b/spec/javascripts/support/jasmine_runner.rb deleted file mode 100644 index f3944f3..0000000 --- a/spec/javascripts/support/jasmine_runner.rb +++ /dev/null @@ -1,32 +0,0 @@ -$:.unshift(ENV['JASMINE_GEM_PATH']) if ENV['JASMINE_GEM_PATH'] # for gem testing purposes - -require 'rubygems' -require 'jasmine' -jasmine_config_overrides = File.expand_path(File.join(File.dirname(__FILE__), 'jasmine_config.rb')) -require jasmine_config_overrides if File.exist?(jasmine_config_overrides) -if Jasmine::Dependencies.rspec2? - require 'rspec' -else - require 'spec' -end - -jasmine_config = Jasmine::Config.new -spec_builder = Jasmine::SpecBuilder.new(jasmine_config) - -should_stop = false - -if Jasmine::Dependencies.rspec2? - RSpec.configuration.after(:suite) do - spec_builder.stop if should_stop - end -else - Spec::Runner.configure do |config| - config.after(:suite) do - spec_builder.stop if should_stop - end - end -end - -spec_builder.start -should_stop = true -spec_builder.declare_suites diff --git a/src/tests/aspectos.js b/src/tests/aspectos.js index 0c8d053..0b36bea 100644 --- a/src/tests/aspectos.js +++ b/src/tests/aspectos.js @@ -23,7 +23,7 @@ describe('Aspectos basic behaviour', function() { testValue += '1'; }); testObject.write(); - expect(testValue).toBe('1 2'); + expect(testValue).to.equal('1 2'); }); it('applies "after" aspect correctly', function() { @@ -36,7 +36,7 @@ describe('Aspectos basic behaviour', function() { testValue += ' 2'; }); testObject.write(); - expect(testValue).toBe('1 2'); + expect(testValue).to.equal('1 2'); }); it('applies "around" aspect correctly', function() { @@ -58,7 +58,7 @@ describe('Aspectos basic behaviour', function() { ] ); testObject.write(); - expect(testValue).toBe('1 2'); + expect(testValue).to.equal('1 2'); }); it('when "before" must pass through original arguments correctly', function() { @@ -76,7 +76,7 @@ describe('Aspectos basic behaviour', function() { ); testObject.write('text'); - expect(testValue).toBe('texttext'); + expect(testValue).to.equal('texttext'); }); it('when "after" must pass through original arguments correctly', function() { @@ -94,7 +94,7 @@ describe('Aspectos basic behaviour', function() { ); testObject.write('text'); - expect(testValue).toBe('texttext'); + expect(testValue).to.equal('texttext'); }); it('when "around" must pass through original arguments correctly', function() { @@ -116,7 +116,7 @@ describe('Aspectos basic behaviour', function() { ] ); testObject.write('text'); - expect(testValue).toBe('texttexttext'); + expect(testValue).to.equal('texttexttext'); }); it('"after" must receive original return values correctly', function() { @@ -136,7 +136,7 @@ describe('Aspectos basic behaviour', function() { ); testObject.write('text'); - expect(testValue).toBe('texttextTEXT'); + expect(testValue).to.equal('texttextTEXT'); }); it('"around" must receive original return values correctly', function() { @@ -161,6 +161,6 @@ describe('Aspectos basic behaviour', function() { ] ); testObject.write('text'); - expect(testValue).toBe('texttexttextTEXT'); + expect(testValue).to.equal('texttexttextTEXT'); }); -}); +}); \ No newline at end of file diff --git a/src/tests/index.html b/src/tests/index.html index 88a53cb..9ae4738 100644 --- a/src/tests/index.html +++ b/src/tests/index.html @@ -2,23 +2,39 @@ Aspectos Tests - + + - - - + + + + + + - + + + + if (location.hash.indexOf('#ci') === -1) { + document.write(' + + +
\ No newline at end of file From 84b7746a7ccbb8e613217f0619fd05b0e030e891 Mon Sep 17 00:00:00 2001 From: Lawrence Carvalho Date: Sat, 18 Aug 2012 12:50:19 +0200 Subject: [PATCH 2/2] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c14853c..faf698f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "aspectos", "description": "Small and simple AOP library", - "version": "1.0.1", + "version": "1.0.2", "keywords": ["aspectos", "aop", "aspect", "ender"], "homepage": "http://github.com/lawrencec/aspectos", "authors": ["Lawrence Carvalho"],