mirror of
https://github.com/lloeki/uspec-js.git
synced 2025-12-06 02:24:40 +01:00
uspec.js: first public release
This commit is contained in:
commit
ec516c106c
8 changed files with 769 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
*.js
|
||||||
24
LICENSE
Normal file
24
LICENSE
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
Copyright (c) 2013, Loic Nageleisen
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the copyright holder nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
22
Makefile
Normal file
22
Makefile
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
all: release
|
||||||
|
|
||||||
|
release: uspec.js
|
||||||
|
|
||||||
|
%.js: %.coffee
|
||||||
|
coffee --compile $<
|
||||||
|
|
||||||
|
run_spec.js: fake_module.js uspec.js uspec_spec.js
|
||||||
|
cat $^ > $@
|
||||||
|
|
||||||
|
node_spec: uspec_spec.js uspec.js
|
||||||
|
node $<
|
||||||
|
|
||||||
|
phantom_spec: run_spec.js
|
||||||
|
phantomjs $<
|
||||||
|
|
||||||
|
spec: node_spec phantom_spec
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@rm -f *.js
|
||||||
|
|
||||||
|
.PHONY: release node_spec phantom_spec spec
|
||||||
4
README.mdown
Normal file
4
README.mdown
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
# µSpec
|
||||||
|
|
||||||
|
µSpec is a minimalist, easy to use spec system that runs in various
|
||||||
|
environments, from nodejs to browsers.
|
||||||
4
fake_module.coffee
Normal file
4
fake_module.coffee
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
root = global || window
|
||||||
|
root.exports = {}
|
||||||
|
root.require = -> exports
|
||||||
|
|
||||||
205
uspec.coffee
Normal file
205
uspec.coffee
Normal file
|
|
@ -0,0 +1,205 @@
|
||||||
|
###
|
||||||
|
# uspec.js v0.5
|
||||||
|
# (c) 2013 Loic Nageleisen
|
||||||
|
# Licensed under 3-clause BSD
|
||||||
|
###
|
||||||
|
|
||||||
|
class Ansi
|
||||||
|
@CSI = "\x1B["
|
||||||
|
@END = "m"
|
||||||
|
|
||||||
|
@BLACK = 0
|
||||||
|
@RED = 1
|
||||||
|
@GREEN = 2
|
||||||
|
@YELLOW = 3
|
||||||
|
@BLUE = 4
|
||||||
|
@MAGENTA = 5
|
||||||
|
@CYAN = 6
|
||||||
|
@WHITE = 7
|
||||||
|
|
||||||
|
@FORE = 30
|
||||||
|
@BACK = 40
|
||||||
|
|
||||||
|
@SGR_RESET = @CSI + @END
|
||||||
|
@SGR_BLACK = @CSI + (@FORE + @BLACK) + @END
|
||||||
|
@SGR_RED = @CSI + (@FORE + @RED) + @END
|
||||||
|
@SGR_GREEN = @CSI + (@FORE + @GREEN) + @END
|
||||||
|
@SGR_YELLOW = @CSI + (@FORE + @YELLOW) + @END
|
||||||
|
@SGR_BLUE = @CSI + (@FORE + @BLUE) + @END
|
||||||
|
@SGR_MAGENTA = @CSI + (@FORE + @MAGENTA) + @END
|
||||||
|
@SGR_CYAN = @CSI + (@FORE + @CYAN) + @END
|
||||||
|
@SGR_WHITE = @CSI + (@FORE + @WHITE) + @END
|
||||||
|
|
||||||
|
|
||||||
|
indent = (str, level = 0) ->
|
||||||
|
str = indent(str, level - 1) if level > 0
|
||||||
|
str.replace(/^/gm, ' ')
|
||||||
|
|
||||||
|
|
||||||
|
all_examples = {}
|
||||||
|
|
||||||
|
|
||||||
|
describe = (target) ->
|
||||||
|
[setup, teardown, examples] = switch arguments.length
|
||||||
|
when 2 then [(-> {}), (->), arguments[1]]
|
||||||
|
when 3 then [arguments[1], (->), arguments[2]]
|
||||||
|
else [arguments[1], arguments[2], arguments[3]]
|
||||||
|
|
||||||
|
all_examples[target] =
|
||||||
|
setup: setup
|
||||||
|
teardown: teardown
|
||||||
|
examples: examples
|
||||||
|
|
||||||
|
|
||||||
|
class AssertionError
|
||||||
|
constructor: (@message) ->
|
||||||
|
toString: -> "AssertionError: #{@message}"
|
||||||
|
|
||||||
|
|
||||||
|
class PendingError
|
||||||
|
constructor: (@message) ->
|
||||||
|
toString: -> "PendingError: #{@message}"
|
||||||
|
|
||||||
|
|
||||||
|
assert = (callback) ->
|
||||||
|
unless callback() == true
|
||||||
|
throw new AssertionError "assertion failed:\n#{indent callback.toString()}"
|
||||||
|
|
||||||
|
|
||||||
|
assert_throws = (exception, callback) ->
|
||||||
|
try
|
||||||
|
callback()
|
||||||
|
catch e
|
||||||
|
return if e instanceof exception
|
||||||
|
throw e
|
||||||
|
throw new AssertionError "assertion failed:\n#{indent callback.toString()}"
|
||||||
|
|
||||||
|
|
||||||
|
pending = (message = '') ->
|
||||||
|
throw new PendingError message
|
||||||
|
|
||||||
|
|
||||||
|
run = (log = new Log(new AnsiWriter)) ->
|
||||||
|
for target, info of all_examples
|
||||||
|
log.current target
|
||||||
|
for example, test of info.examples
|
||||||
|
try
|
||||||
|
throw new PendingError if test.toString() == (->).toString()
|
||||||
|
test.call(info.setup())
|
||||||
|
info.teardown()
|
||||||
|
log.pass example
|
||||||
|
catch e
|
||||||
|
if e instanceof AssertionError
|
||||||
|
log.fail example, e
|
||||||
|
else if e instanceof PendingError
|
||||||
|
log.pending example, e
|
||||||
|
else
|
||||||
|
log.fail example, e
|
||||||
|
|
||||||
|
log.results
|
||||||
|
|
||||||
|
|
||||||
|
PASS = 'pass'
|
||||||
|
FAIL = 'fail'
|
||||||
|
PENDING = 'pending'
|
||||||
|
|
||||||
|
|
||||||
|
class Log
|
||||||
|
constructor: (@writer = new NaiveWriter) ->
|
||||||
|
@results = {}
|
||||||
|
|
||||||
|
log: (example, status, message = '') ->
|
||||||
|
@results[@target][example] =
|
||||||
|
status: status
|
||||||
|
message: message
|
||||||
|
|
||||||
|
current: (target) ->
|
||||||
|
@target = target
|
||||||
|
@results[@target] = {}
|
||||||
|
@writer.current(target)
|
||||||
|
|
||||||
|
pass: (example) ->
|
||||||
|
this.log(example, PASS)
|
||||||
|
@writer.pass(example)
|
||||||
|
|
||||||
|
fail: (example, e) ->
|
||||||
|
this.log(example, FAIL, e.message)
|
||||||
|
@writer.fail(example)
|
||||||
|
|
||||||
|
pending: (example, p) ->
|
||||||
|
this.log(example, PENDING)
|
||||||
|
@writer.pending(example, p.message)
|
||||||
|
|
||||||
|
|
||||||
|
summary = (results) ->
|
||||||
|
total =
|
||||||
|
pass: 0
|
||||||
|
fail: 0
|
||||||
|
pending: 0
|
||||||
|
for target, examples of results
|
||||||
|
for example, result of examples
|
||||||
|
switch result.status
|
||||||
|
when PASS then total.pass += 1
|
||||||
|
when FAIL then total.fail += 1
|
||||||
|
when PENDING then total.pending += 1
|
||||||
|
total.all = total.pass + total.fail + total.pending
|
||||||
|
|
||||||
|
console.log ''
|
||||||
|
console.log 'Failures:\n' if total.fail > 0
|
||||||
|
counter = 0
|
||||||
|
for target, examples of results
|
||||||
|
for example, result of examples
|
||||||
|
if result.status == FAIL
|
||||||
|
counter += 1
|
||||||
|
console.log indent "#{counter}) #{Ansi.SGR_RED}#{target} #{example}#{Ansi.SGR_RESET}"
|
||||||
|
unless result.message is undefined
|
||||||
|
console.log indent(result.message, 2) + "\n"
|
||||||
|
|
||||||
|
console.log "#{total.all} examples, #{total.fail} failure, #{total.pending} pending"
|
||||||
|
|
||||||
|
total.fail == 0
|
||||||
|
|
||||||
|
|
||||||
|
class AnsiWriter
|
||||||
|
constructor: ->
|
||||||
|
current: (target) -> console.log "\n#{target}"
|
||||||
|
pass: (example) -> console.log " #{Ansi.SGR_GREEN}#{example}#{Ansi.SGR_RESET}"
|
||||||
|
fail: (example) -> console.log " #{Ansi.SGR_RED}#{example}#{Ansi.SGR_RESET}"
|
||||||
|
pending: (example) -> console.log " #{Ansi.SGR_YELLOW}#{example}#{Ansi.SGR_RESET}"
|
||||||
|
|
||||||
|
|
||||||
|
class AnsiDotWriter
|
||||||
|
current: (target) ->
|
||||||
|
pass: (example) -> console.log "#{Ansi.SGR_GREEN}.#{Ansi.SGR_RESET}"
|
||||||
|
fail: (example) -> console.log "#{Ansi.SGR_RED}F#{Ansi.SGR_RESET}"
|
||||||
|
pending: (example) -> console.log "#{Ansi.SGR_YELLOW}##{Ansi.SGR_RESET}"
|
||||||
|
|
||||||
|
|
||||||
|
class DotWriter
|
||||||
|
current: (target) ->
|
||||||
|
pass: (example) -> console.log "."
|
||||||
|
fail: (example) -> console.log "F"
|
||||||
|
pending: (example) -> console.log "#"
|
||||||
|
|
||||||
|
|
||||||
|
class NaiveWriter
|
||||||
|
current: (target) -> console.log "#{target}"
|
||||||
|
pass: (example) -> console.log " #{example}: pass"
|
||||||
|
fail: (example) -> console.log " #{example}: fail"
|
||||||
|
pending: (example) -> console.log " #{example}: pending"
|
||||||
|
|
||||||
|
class NullWriter
|
||||||
|
current: ->
|
||||||
|
pass: ->
|
||||||
|
fail: ->
|
||||||
|
pending: ->
|
||||||
|
|
||||||
|
|
||||||
|
exports.run = run
|
||||||
|
exports.describe = describe
|
||||||
|
exports.assert = assert
|
||||||
|
exports.assert_throws = assert_throws
|
||||||
|
exports.pending = pending
|
||||||
|
exports.summary = summary
|
||||||
|
exports.AssertionError = AssertionError
|
||||||
|
exports.PendingError = PendingError
|
||||||
398
uspec.js
Normal file
398
uspec.js
Normal file
|
|
@ -0,0 +1,398 @@
|
||||||
|
// Generated by CoffeeScript 1.6.2
|
||||||
|
/*
|
||||||
|
# uspec.js v0.5
|
||||||
|
# (c) 2013 Loic Nageleisen
|
||||||
|
# Licensed under 3-clause BSD
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
var Ansi, AnsiDotWriter, AnsiWriter, AssertionError, DotWriter, FAIL, Log, NaiveWriter, NullWriter, PASS, PENDING, PendingError, all_examples, assert, assert_throws, describe, indent, pending, run, summary;
|
||||||
|
|
||||||
|
Ansi = (function() {
|
||||||
|
function Ansi() {}
|
||||||
|
|
||||||
|
Ansi.CSI = "\x1B[";
|
||||||
|
|
||||||
|
Ansi.END = "m";
|
||||||
|
|
||||||
|
Ansi.BLACK = 0;
|
||||||
|
|
||||||
|
Ansi.RED = 1;
|
||||||
|
|
||||||
|
Ansi.GREEN = 2;
|
||||||
|
|
||||||
|
Ansi.YELLOW = 3;
|
||||||
|
|
||||||
|
Ansi.BLUE = 4;
|
||||||
|
|
||||||
|
Ansi.MAGENTA = 5;
|
||||||
|
|
||||||
|
Ansi.CYAN = 6;
|
||||||
|
|
||||||
|
Ansi.WHITE = 7;
|
||||||
|
|
||||||
|
Ansi.FORE = 30;
|
||||||
|
|
||||||
|
Ansi.BACK = 40;
|
||||||
|
|
||||||
|
Ansi.SGR_RESET = Ansi.CSI + Ansi.END;
|
||||||
|
|
||||||
|
Ansi.SGR_BLACK = Ansi.CSI + (Ansi.FORE + Ansi.BLACK) + Ansi.END;
|
||||||
|
|
||||||
|
Ansi.SGR_RED = Ansi.CSI + (Ansi.FORE + Ansi.RED) + Ansi.END;
|
||||||
|
|
||||||
|
Ansi.SGR_GREEN = Ansi.CSI + (Ansi.FORE + Ansi.GREEN) + Ansi.END;
|
||||||
|
|
||||||
|
Ansi.SGR_YELLOW = Ansi.CSI + (Ansi.FORE + Ansi.YELLOW) + Ansi.END;
|
||||||
|
|
||||||
|
Ansi.SGR_BLUE = Ansi.CSI + (Ansi.FORE + Ansi.BLUE) + Ansi.END;
|
||||||
|
|
||||||
|
Ansi.SGR_MAGENTA = Ansi.CSI + (Ansi.FORE + Ansi.MAGENTA) + Ansi.END;
|
||||||
|
|
||||||
|
Ansi.SGR_CYAN = Ansi.CSI + (Ansi.FORE + Ansi.CYAN) + Ansi.END;
|
||||||
|
|
||||||
|
Ansi.SGR_WHITE = Ansi.CSI + (Ansi.FORE + Ansi.WHITE) + Ansi.END;
|
||||||
|
|
||||||
|
return Ansi;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
indent = function(str, level) {
|
||||||
|
if (level == null) {
|
||||||
|
level = 0;
|
||||||
|
}
|
||||||
|
if (level > 0) {
|
||||||
|
str = indent(str, level - 1);
|
||||||
|
}
|
||||||
|
return str.replace(/^/gm, ' ');
|
||||||
|
};
|
||||||
|
|
||||||
|
all_examples = {};
|
||||||
|
|
||||||
|
describe = function(target) {
|
||||||
|
var examples, setup, teardown, _ref;
|
||||||
|
|
||||||
|
_ref = (function() {
|
||||||
|
switch (arguments.length) {
|
||||||
|
case 2:
|
||||||
|
return [
|
||||||
|
(function() {
|
||||||
|
return {};
|
||||||
|
}), (function() {}), arguments[1]
|
||||||
|
];
|
||||||
|
case 3:
|
||||||
|
return [arguments[1], (function() {}), arguments[2]];
|
||||||
|
default:
|
||||||
|
return [arguments[1], arguments[2], arguments[3]];
|
||||||
|
}
|
||||||
|
}).apply(this, arguments), setup = _ref[0], teardown = _ref[1], examples = _ref[2];
|
||||||
|
return all_examples[target] = {
|
||||||
|
setup: setup,
|
||||||
|
teardown: teardown,
|
||||||
|
examples: examples
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
AssertionError = (function() {
|
||||||
|
function AssertionError(message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertionError.prototype.toString = function() {
|
||||||
|
return "AssertionError: " + this.message;
|
||||||
|
};
|
||||||
|
|
||||||
|
return AssertionError;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
PendingError = (function() {
|
||||||
|
function PendingError(message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
PendingError.prototype.toString = function() {
|
||||||
|
return "PendingError: " + this.message;
|
||||||
|
};
|
||||||
|
|
||||||
|
return PendingError;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
assert = function(callback) {
|
||||||
|
if (callback() !== true) {
|
||||||
|
throw new AssertionError("assertion failed:\n" + (indent(callback.toString())));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_throws = function(exception, callback) {
|
||||||
|
var e;
|
||||||
|
|
||||||
|
try {
|
||||||
|
callback();
|
||||||
|
} catch (_error) {
|
||||||
|
e = _error;
|
||||||
|
if (e instanceof exception) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
throw new AssertionError("assertion failed:\n" + (indent(callback.toString())));
|
||||||
|
};
|
||||||
|
|
||||||
|
pending = function(message) {
|
||||||
|
if (message == null) {
|
||||||
|
message = '';
|
||||||
|
}
|
||||||
|
throw new PendingError(message);
|
||||||
|
};
|
||||||
|
|
||||||
|
run = function(log) {
|
||||||
|
var e, example, info, target, test, _ref;
|
||||||
|
|
||||||
|
if (log == null) {
|
||||||
|
log = new Log(new AnsiWriter);
|
||||||
|
}
|
||||||
|
for (target in all_examples) {
|
||||||
|
info = all_examples[target];
|
||||||
|
log.current(target);
|
||||||
|
_ref = info.examples;
|
||||||
|
for (example in _ref) {
|
||||||
|
test = _ref[example];
|
||||||
|
try {
|
||||||
|
if (test.toString() === (function() {}).toString()) {
|
||||||
|
throw new PendingError;
|
||||||
|
}
|
||||||
|
test.call(info.setup());
|
||||||
|
info.teardown();
|
||||||
|
log.pass(example);
|
||||||
|
} catch (_error) {
|
||||||
|
e = _error;
|
||||||
|
if (e instanceof AssertionError) {
|
||||||
|
log.fail(example, e);
|
||||||
|
} else if (e instanceof PendingError) {
|
||||||
|
log.pending(example, e);
|
||||||
|
} else {
|
||||||
|
log.fail(example, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return log.results;
|
||||||
|
};
|
||||||
|
|
||||||
|
PASS = 'pass';
|
||||||
|
|
||||||
|
FAIL = 'fail';
|
||||||
|
|
||||||
|
PENDING = 'pending';
|
||||||
|
|
||||||
|
Log = (function() {
|
||||||
|
function Log(writer) {
|
||||||
|
this.writer = writer != null ? writer : new NaiveWriter;
|
||||||
|
this.results = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.prototype.log = function(example, status, message) {
|
||||||
|
if (message == null) {
|
||||||
|
message = '';
|
||||||
|
}
|
||||||
|
return this.results[this.target][example] = {
|
||||||
|
status: status,
|
||||||
|
message: message
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Log.prototype.current = function(target) {
|
||||||
|
this.target = target;
|
||||||
|
this.results[this.target] = {};
|
||||||
|
return this.writer.current(target);
|
||||||
|
};
|
||||||
|
|
||||||
|
Log.prototype.pass = function(example) {
|
||||||
|
this.log(example, PASS);
|
||||||
|
return this.writer.pass(example);
|
||||||
|
};
|
||||||
|
|
||||||
|
Log.prototype.fail = function(example, e) {
|
||||||
|
this.log(example, FAIL, e.message);
|
||||||
|
return this.writer.fail(example);
|
||||||
|
};
|
||||||
|
|
||||||
|
Log.prototype.pending = function(example, p) {
|
||||||
|
this.log(example, PENDING);
|
||||||
|
return this.writer.pending(example, p.message);
|
||||||
|
};
|
||||||
|
|
||||||
|
return Log;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
summary = function(results) {
|
||||||
|
var counter, example, examples, result, target, total;
|
||||||
|
|
||||||
|
total = {
|
||||||
|
pass: 0,
|
||||||
|
fail: 0,
|
||||||
|
pending: 0
|
||||||
|
};
|
||||||
|
for (target in results) {
|
||||||
|
examples = results[target];
|
||||||
|
for (example in examples) {
|
||||||
|
result = examples[example];
|
||||||
|
switch (result.status) {
|
||||||
|
case PASS:
|
||||||
|
total.pass += 1;
|
||||||
|
break;
|
||||||
|
case FAIL:
|
||||||
|
total.fail += 1;
|
||||||
|
break;
|
||||||
|
case PENDING:
|
||||||
|
total.pending += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
total.all = total.pass + total.fail + total.pending;
|
||||||
|
console.log('');
|
||||||
|
if (total.fail > 0) {
|
||||||
|
console.log('Failures:\n');
|
||||||
|
}
|
||||||
|
counter = 0;
|
||||||
|
for (target in results) {
|
||||||
|
examples = results[target];
|
||||||
|
for (example in examples) {
|
||||||
|
result = examples[example];
|
||||||
|
if (result.status === FAIL) {
|
||||||
|
counter += 1;
|
||||||
|
console.log(indent("" + counter + ") " + Ansi.SGR_RED + target + " " + example + Ansi.SGR_RESET));
|
||||||
|
if (result.message !== void 0) {
|
||||||
|
console.log(indent(result.message, 2) + "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log("" + total.all + " examples, " + total.fail + " failure, " + total.pending + " pending");
|
||||||
|
return total.fail === 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
AnsiWriter = (function() {
|
||||||
|
function AnsiWriter() {}
|
||||||
|
|
||||||
|
AnsiWriter.prototype.current = function(target) {
|
||||||
|
return console.log("\n" + target);
|
||||||
|
};
|
||||||
|
|
||||||
|
AnsiWriter.prototype.pass = function(example) {
|
||||||
|
return console.log(" " + Ansi.SGR_GREEN + example + Ansi.SGR_RESET);
|
||||||
|
};
|
||||||
|
|
||||||
|
AnsiWriter.prototype.fail = function(example) {
|
||||||
|
return console.log(" " + Ansi.SGR_RED + example + Ansi.SGR_RESET);
|
||||||
|
};
|
||||||
|
|
||||||
|
AnsiWriter.prototype.pending = function(example) {
|
||||||
|
return console.log(" " + Ansi.SGR_YELLOW + example + Ansi.SGR_RESET);
|
||||||
|
};
|
||||||
|
|
||||||
|
return AnsiWriter;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
AnsiDotWriter = (function() {
|
||||||
|
function AnsiDotWriter() {}
|
||||||
|
|
||||||
|
AnsiDotWriter.prototype.current = function(target) {};
|
||||||
|
|
||||||
|
AnsiDotWriter.prototype.pass = function(example) {
|
||||||
|
return console.log("" + Ansi.SGR_GREEN + "." + Ansi.SGR_RESET);
|
||||||
|
};
|
||||||
|
|
||||||
|
AnsiDotWriter.prototype.fail = function(example) {
|
||||||
|
return console.log("" + Ansi.SGR_RED + "F" + Ansi.SGR_RESET);
|
||||||
|
};
|
||||||
|
|
||||||
|
AnsiDotWriter.prototype.pending = function(example) {
|
||||||
|
return console.log("" + Ansi.SGR_YELLOW + "#" + Ansi.SGR_RESET);
|
||||||
|
};
|
||||||
|
|
||||||
|
return AnsiDotWriter;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
DotWriter = (function() {
|
||||||
|
function DotWriter() {}
|
||||||
|
|
||||||
|
DotWriter.prototype.current = function(target) {};
|
||||||
|
|
||||||
|
DotWriter.prototype.pass = function(example) {
|
||||||
|
return console.log(".");
|
||||||
|
};
|
||||||
|
|
||||||
|
DotWriter.prototype.fail = function(example) {
|
||||||
|
return console.log("F");
|
||||||
|
};
|
||||||
|
|
||||||
|
DotWriter.prototype.pending = function(example) {
|
||||||
|
return console.log("#");
|
||||||
|
};
|
||||||
|
|
||||||
|
return DotWriter;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
NaiveWriter = (function() {
|
||||||
|
function NaiveWriter() {}
|
||||||
|
|
||||||
|
NaiveWriter.prototype.current = function(target) {
|
||||||
|
return console.log("" + target);
|
||||||
|
};
|
||||||
|
|
||||||
|
NaiveWriter.prototype.pass = function(example) {
|
||||||
|
return console.log(" " + example + ": pass");
|
||||||
|
};
|
||||||
|
|
||||||
|
NaiveWriter.prototype.fail = function(example) {
|
||||||
|
return console.log(" " + example + ": fail");
|
||||||
|
};
|
||||||
|
|
||||||
|
NaiveWriter.prototype.pending = function(example) {
|
||||||
|
return console.log(" " + example + ": pending");
|
||||||
|
};
|
||||||
|
|
||||||
|
return NaiveWriter;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
NullWriter = (function() {
|
||||||
|
function NullWriter() {}
|
||||||
|
|
||||||
|
NullWriter.prototype.current = function() {};
|
||||||
|
|
||||||
|
NullWriter.prototype.pass = function() {};
|
||||||
|
|
||||||
|
NullWriter.prototype.fail = function() {};
|
||||||
|
|
||||||
|
NullWriter.prototype.pending = function() {};
|
||||||
|
|
||||||
|
return NullWriter;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
exports.run = run;
|
||||||
|
|
||||||
|
exports.describe = describe;
|
||||||
|
|
||||||
|
exports.assert = assert;
|
||||||
|
|
||||||
|
exports.assert_throws = assert_throws;
|
||||||
|
|
||||||
|
exports.pending = pending;
|
||||||
|
|
||||||
|
exports.summary = summary;
|
||||||
|
|
||||||
|
exports.AssertionError = AssertionError;
|
||||||
|
|
||||||
|
exports.PendingError = PendingError;
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
111
uspec_spec.coffee
Normal file
111
uspec_spec.coffee
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
minispec = require('./uspec')
|
||||||
|
|
||||||
|
describe = minispec.describe
|
||||||
|
assert = minispec.assert
|
||||||
|
assert_throws = minispec.assert_throws
|
||||||
|
pending = minispec.pending
|
||||||
|
run = minispec.run
|
||||||
|
summary = minispec.summary
|
||||||
|
|
||||||
|
|
||||||
|
describe 'AssertionError',
|
||||||
|
'should be exported': ->
|
||||||
|
assert -> typeof minispec.AssertionError isnt 'undefined'
|
||||||
|
'should take a message': ->
|
||||||
|
assert -> (new minispec.AssertionError 'foo').message == 'foo'
|
||||||
|
'should render as an error string': ->
|
||||||
|
str = (new minispec.AssertionError 'foo').toString()
|
||||||
|
assert -> str == "AssertionError: foo"
|
||||||
|
|
||||||
|
|
||||||
|
describe 'PendingError',
|
||||||
|
'should be exported': ->
|
||||||
|
assert -> typeof minispec.PendingError isnt 'undefined'
|
||||||
|
'should take a message': ->
|
||||||
|
assert -> (new minispec.PendingError 'foo').message == 'foo'
|
||||||
|
'should render as an error string': ->
|
||||||
|
str = (new minispec.PendingError 'foo').toString()
|
||||||
|
assert -> str == "PendingError: foo"
|
||||||
|
|
||||||
|
|
||||||
|
describe 'pending',
|
||||||
|
'should be exported': ->
|
||||||
|
assert -> typeof minispec.pending isnt 'undefined'
|
||||||
|
|
||||||
|
'should throw a PendingError containing a blank message': ->
|
||||||
|
try
|
||||||
|
pending()
|
||||||
|
catch e
|
||||||
|
assert -> e instanceof minispec.PendingError
|
||||||
|
assert -> e.message == ''
|
||||||
|
|
||||||
|
'should throw a PendingError containing a message': ->
|
||||||
|
try
|
||||||
|
pending('foo')
|
||||||
|
catch e
|
||||||
|
assert -> e instanceof minispec.PendingError
|
||||||
|
assert -> e.message == 'foo'
|
||||||
|
|
||||||
|
|
||||||
|
describe 'assert',
|
||||||
|
'should be exported': ->
|
||||||
|
assert -> typeof minispec.assert isnt 'undefined'
|
||||||
|
|
||||||
|
'should pass without throwing when assertion returns true': ->
|
||||||
|
do ->
|
||||||
|
minispec.assert -> true
|
||||||
|
|
||||||
|
'should throw AssertionError when assertion does not return true': ->
|
||||||
|
try
|
||||||
|
minispec.assert -> false
|
||||||
|
catch e
|
||||||
|
unless e instanceof minispec.AssertionError
|
||||||
|
throw new AssertionError
|
||||||
|
|
||||||
|
'should rethrow exception when assertion throws an exception': ->
|
||||||
|
try
|
||||||
|
minispec.assert -> throw new Error 'foo'
|
||||||
|
catch e
|
||||||
|
unless e instanceof Error
|
||||||
|
throw new AssertionError
|
||||||
|
unless e.message == 'foo'
|
||||||
|
throw new AssertionError
|
||||||
|
|
||||||
|
|
||||||
|
describe 'assert_throws',
|
||||||
|
'should be exported': ->
|
||||||
|
assert -> typeof minispec.assert_throws isnt 'undefined'
|
||||||
|
|
||||||
|
'should pass when block throws the expected exception': ->
|
||||||
|
class FooError
|
||||||
|
do ->
|
||||||
|
minispec.assert_throws FooError, -> throw new FooError
|
||||||
|
|
||||||
|
'should throw AssertionError when block does not throw any exception': ->
|
||||||
|
class FooError
|
||||||
|
try
|
||||||
|
minispec.assert_throws FooError, -> 42
|
||||||
|
catch e
|
||||||
|
assert -> e instanceof minispec.AssertionError
|
||||||
|
|
||||||
|
'should rethrow exception when block throws an unexpected exception': ->
|
||||||
|
class FooError
|
||||||
|
class BarError
|
||||||
|
try
|
||||||
|
minispec.assert_throws FooError, -> throw new BarError
|
||||||
|
catch e
|
||||||
|
assert -> e instanceof BarError
|
||||||
|
|
||||||
|
describe 'describe',
|
||||||
|
'should be exported': ->
|
||||||
|
assert -> typeof minispec.describe isnt 'undefined'
|
||||||
|
|
||||||
|
describe 'run',
|
||||||
|
'should be exported': ->
|
||||||
|
assert -> typeof minispec.run isnt 'undefined'
|
||||||
|
|
||||||
|
results = run()
|
||||||
|
rc = if summary(results) then 0 else 1
|
||||||
|
|
||||||
|
phantom.exit(rc) unless typeof phantom is 'undefined'
|
||||||
|
process.exit(rc) unless typeof process is 'undefined'
|
||||||
Loading…
Add table
Add a link
Reference in a new issue