383f9aa0e566d064202f58fc1f6bed58630fff19.svn-base
3.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
'use strict'
const t = require('./tap.js')
t.jobs = 1
const tapStack = [ t ]
let level = 0
const suiteStack = []
const describe = (name, fn, opt) =>
new Suite(name, fn, opt)
class Suite {
constructor (name, fn, opt) {
this.parent = suiteStack[ suiteStack.length - 1 ]
if (typeof name === 'function')
fn = name, name = null
if (fn && fn.name && !name)
name = fn.name
this.options = opt || {}
this.options.todo = this.options.todo || !fn
this.fn = fn
this.name = name
this.after = []
this.test = null
this.run()
}
run () {
const t = tapStack[ tapStack.length - 1 ]
t.test(this.name, this.options, tt => {
this.test = tt
tapStack.push(tt)
suiteStack.push(this)
const ret = this.fn()
this.runAfter()
suiteStack.pop()
return ret
})
}
runAfter () {
this.after.forEach(a =>
before(a[0], a[1], a[2]))
let t
do {
t = tapStack.pop()
} while (t && t !== this.test)
if (this.test && !this.test.results)
t.end()
}
}
const before = (name, fn, options) => {
if (typeof name === 'function')
fn = name, name = null
if (fn && fn.name && !name)
name = fn.name
options = options || {}
const todo = !fn
options.todo = options.todo || todo
options.silent = true
const suite = suiteStack[ suiteStack.length - 1 ]
if (!suite)
throw new Error('cannot call "before" outside of describe()')
const t = tapStack[ tapStack.length - 1 ]
if (!name)
name = ''
const done = tt => er => er ? tt.threw(er) : tt.end()
t.test(name, options, tt => {
const ret = fn.call(suite, done(tt))
if (!ret && fn.length === 0)
tt.end()
else
return ret
})
}
const it = (name, fn, options) => {
if (typeof name === 'function')
fn = name, name = null
if (fn && fn.name && !name)
name = fn.name
options = options || {}
const todo = !fn
const suite = suiteStack[ suiteStack.length - 1 ]
const t = tapStack[ tapStack.length - 1 ]
if (!name)
name = ''
const done = tt => er => er ? tt.threw(er) : tt.end()
options.todo = options.todo || todo
options.tapMochaTest = true
t.test(name, options, tt => {
const ret = fn.call(tt, done(tt))
if (ret && ret.then)
return ret
else if (fn.length === 0)
tt.end()
})
}
it.skip = (name, fn) => it(name, fn, { skip: true })
it.todo = (name, fn) => it(name, fn, { todo: true })
function after (name, fn, options) {
const suite = suiteStack[ suiteStack.length - 1 ]
if (!suite)
throw new Error('cannot call "after" outside of describe()')
suite.after.push([name, fn, options])
}
function moment (when, fn) {
const t = tapStack[ tapStack.length - 1 ]
// need function because 'this' tells us which tap object
// has the tapMochaTest thing in its options object
t[when](function (cb) {
if (!this.options.tapMochaTest)
return cb()
const suite = suiteStack[ suiteStack.length - 1 ]
const ret = fn.call(this, cb)
if (ret && ret.then)
return ret
else if (fn.length === 0)
return cb()
})
}
const beforeEach = fn =>
moment('beforeEach', fn)
const afterEach = fn =>
moment('afterEach', fn)
exports.it = exports.specify = it
exports.context = exports.describe = describe
exports.before = before
exports.after = after
exports.beforeEach = beforeEach
exports.afterEach = afterEach
let saved
exports.global = _ => {
if (!saved)
saved = new Map()
Object.keys(exports).filter(g => g !== 'global').forEach(g => {
if (!saved.has(g))
saved.set(g, global[g])
global[g] = exports[g]
})
}
exports.deglobal = _ =>
Object.keys(exports).filter(g => g !== 'global').forEach(g => {
if (saved && saved.has(g))
global[g] = saved.get(g)
})