-
Notifications
You must be signed in to change notification settings - Fork 0
/
reload.coffee
170 lines (130 loc) · 4.22 KB
/
reload.coffee
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
159
160
161
162
163
164
165
166
167
168
169
170
rewire = require 'rewire'
sinon = require 'sinon'
EventEmitter = require('events').EventEmitter
describe "reload-json", ->
Reload = rewire '../../lib/reload'
reload = null
watch = null
fsMock = {}
Reload.__set__ 'fs', fsMock
beforeEach ->
watch = new EventEmitter
reload = new Reload
fsMock.watch = sinon.stub().returns watch
fsMock.readFile = sinon.stub()
.callsArgWithAsync 1, null, '{"key": "data"}'
describe "#read", ->
it "returns an EventEmitter", ->
read = reload.read 'foo'
assert.isFunction read.on
it "calls readFile", ->
reload.read 'foo'
assert.calledOnce fsMock.readFile
assert.calledWith fsMock.readFile, 'foo'
it "handels file once loaded", (done) ->
reload.on 'load', ->
assert.propertyVal reload.files.foo, 'key', 'data'
done()
reload.read 'foo'
it "deals with errors while reading the file ", (done) ->
err = new Error 'dummy-error'
fsMock.readFile = sinon.stub()
.callsArgWithAsync 1, err
reload.on 'error', ->
assert.propertyVal reload.files, 'foo', null
done()
reload.read 'foo'
it "emits an error when receiving invalid json", (done) ->
reload.on 'error', ->
done()
fsMock.readFile = sinon.stub()
.callsArgWithAsync 1, null, '{blah'
reload.read 'foo'
describe "#configureWatch", ->
it "configures a filesystem watch", (done) ->
reload.configureWatch 'foo'
process.nextTick ->
assert.calledOnce fsMock.watch
assert.calledWith fsMock.watch, 'foo'
done()
it "triggers a read on change", (done) ->
reload.configureWatch 'foo'
watch.emit 'change', 'change', 'foo'
setTimeout (->
assert.calledOnce fsMock.readFile
assert.calledWith fsMock.readFile, 'foo'
done()
), 25
it "checks if a read is in progress before triggering", (done) ->
reload.configureWatch 'foo'
watch.emit 'change', 'change', 'foo'
setTimeout (->
reload.files['foo'] = {}
), 5
setTimeout (->
assert.equal fsMock.readFile.callCount, 0
done()
), 25
it "forwards change event", (done) ->
reload.configureWatch 'foo'
reload.on 'change', (ev, filename) ->
assert.equal filename, 'foo'
# wait for debounce
setTimeout done, 20
watch.emit 'change', 'change', 'foo'
it "forwards any error that occurs", (done) ->
err = new Error 'dummy-error'
reload.configureWatch 'foo'
reload.on 'error', (e) ->
assert.strictEqual e, err
done()
watch.emit 'error', err
describe "#load", ->
it "consolidates two reads into one", (done) ->
readOne = null
readTwo = null
verify = ->
assert.strictEqual readOne, readTwo
assert.calledOnce fsMock.readFile
done()
reload.load 'foo', (err, data) ->
assert.isNull err
readOne = data
verify() if readTwo
reload.load 'foo', (err, data) ->
readTwo = data
verify() if readOne
it "returns cached data", (done) ->
reload.load 'foo', (err, readOne) ->
assert.isNull err
reload.load 'foo', (err, readTwo) ->
assert.isNull err
assert.strictEqual readOne, readTwo
done()
it "forwards error to callback", (done) ->
err = new Error 'dummy-error'
fsMock.readFile = sinon.stub()
.callsArgWithAsync 1, err
reload.on 'error', ->
return
reload.load 'foo', (err, data) ->
assert.instanceOf err, Error
done()
it "cleans up subscribers after loading", (done) ->
callback = sinon.stub()
err = new Error 'dummy-error'
file = new EventEmitter
reload.read = sinon.stub().returns file
reload.load 'foo', callback
file.emit 'error', err
file.emit 'load'
assert.calledOnce callback
assert.calledWith callback, sinon.match.instanceOf Error
assert.lengthOf file.listeners('load'), 0
done()
it "should return a thunk", (done) ->
thunk = reload.load 'foo'
thunk (err, data) ->
assert.isNull err
assert.propertyVal data, 'key', 'data'
done()