mirror of
https://github.com/lloeki/uspec-js.git
synced 2025-12-06 10:34:40 +01:00
uspec.js: first public release
This commit is contained in:
commit
ec516c106c
8 changed files with 769 additions and 0 deletions
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
|
||||
Loading…
Add table
Add a link
Reference in a new issue