-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathrestapi.tester.coffee
More file actions
270 lines (228 loc) · 7.99 KB
/
restapi.tester.coffee
File metadata and controls
270 lines (228 loc) · 7.99 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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# Export Plugin Tester
module.exports = (testers) ->
# PRepare
pathUtil = require('path')
safefs = require('safefs')
{expect} = require('chai')
superAgent = require('superagent')
superAgent['delete'] = superAgent.del
rimraf = require('rimraf')
# Define My Tester
class MyTester extends testers.ServerTester
#docpadConfig:
# port: 9779
# Cleanup
clean: =>
# Prepare
tester = @
testerConfig = tester.getConfig()
# Cleanup
@suite "clean restapi", (suite,test) ->
srcPath = pathUtil.join(testerConfig.testPath, 'src')
test 'remove src', (next) ->
rimraf srcPath, (err) ->
return next() # ignore errors
test 'readd src', (next) ->
safefs.ensurePath(srcPath, next)
# Chain
@
# Test Create
testCreate: => @clean(); super
# Custom test for the server
testServer: (next) ->
# Prepare
tester = @
# Create the server
super
# Test
@suite 'restapi', (suite,test) ->
# Prepare
testerConfig = tester.getConfig()
docpad = tester.docpad
docpadConfig = docpad.getConfig()
plugin = tester.getPlugin()
pluginConfig = plugin.getConfig()
files = []
# Prepare
apiUrl = "http://localhost:#{docpadConfig.port}/restapi"
# Request
request = (method, relativeUrl, requestData, next) ->
absoluteUrl = apiUrl+'/'+relativeUrl
console.log "#{method} to #{absoluteUrl}"
superAgent[method](absoluteUrl)
.type('json').set('Accept', 'application/json')
.send(requestData)
.timeout(30*1000)
.end(next)
# Send and check file
requestWithCheck = (method, url, requestData, responseData, next) ->
request method, url, requestData, (err, res) ->
# Check
return next(err) if err
# Compare
actual = res.body
expected =
success: true
message: null
data: responseData
# Clean
switch method
when 'delete'
expected.message = 'Delete completed successfully'
when 'post'
expected.message = 'Update completed successfully'
when 'put'
expected.message = 'Creation completed successfully'
when 'get'
actual.message =
expected.message = 'Overwritten as this changes'
# Cleanup
items = actual.data
items = [items] if Array.isArray(items) is false
for item in items
delete item.source
delete item.date
delete item.id
# Check
try
expect(actual, 'response result should be as expected').to.deep.equal(expected)
catch err
console.log JSON.stringify(actual, null, ' ')
console.log JSON.stringify(expected, null, ' ')
return next(err)
return next()
# Send and verify unauthorized response
requestWithUnauthorizedCheck = (method, next) ->
request method, 'collection/documents/posts/test.txt', {}, (err, res) ->
# Check
return next(err) if err
# Compare
actual = res.body
expected =
success: false
message: "Unauthorized"
# Check
try
expect(res.status, 'response status was not expected').to.equal(403)
expect(actual, 'response result should be as expected').to.deep.equal(expected)
catch err
console.log JSON.stringify(actual, null, ' ')
console.log JSON.stringify(expected, null, ' ')
return next(err)
return next()
# Collections
suite 'collections', (suite,test) ->
test 'check listing', (done) ->
responseData = []
docpad.eachCollection (collection, collectionName) ->
responseData.push {name:collectionName, length:0, relativePaths:[]}
requestData = {}
requestWithCheck('get', 'collections/', requestData, responseData, done)
# Create files
suite 'create', (suite,test) ->
# Create file test
test "create a new document", (done) ->
responseData =
meta:
title: 'hello world'
filename: 'test.txt'
relativePath: 'posts/test.txt'
url: '/posts/test.txt'
urls: ['/posts/test.txt']
contentType: "text/plain"
encoding: "utf8"
content: 'hello *world*'
contentRendered: 'hello *world*'
requestData =
title: responseData.meta.title
content: responseData.content
files.push(responseData)
requestWithCheck('put', "collection/documents/posts/test.txt", requestData, responseData, done)
# Create file test
test "create a 2nd new document", (done) ->
responseData =
meta:
title: 'hello world'
filename: 'test-2.html'
relativePath: 'posts/test-2.html'
url: '/posts/test-2.html'
urls: ['/posts/test-2.html']
contentType: "text/html"
encoding: "utf8"
content: 'hello *world*'
contentRendered: 'hello *world*'
requestData =
title: responseData.meta.title
content: responseData.content
files.push(responseData)
requestWithCheck('put', "collection/documents/posts/test.html", requestData, responseData, done)
# Create file test
test "create a 3rd new document", (done) ->
responseData =
meta:
title: 'hello world'
filename: 'test-3.html.md'
relativePath: 'posts/test-3.html.md'
url: '/posts/test-3.html'
urls: ['/posts/test-3.html']
contentType: "text/x-markdown"
encoding: "utf8"
content: 'hello *world*'
contentRendered: "<p>hello <em>world</em></p>\n"
requestData =
title: responseData.meta.title
content: responseData.content
files.push(responseData)
requestWithCheck('put', "collection/documents/posts/test.html.md", requestData, responseData, done)
# Check listing
test 'check listing', (done) ->
responseData = files
requestData = {}
requestWithCheck('get', 'collection/documents/', requestData, responseData, done)
# Delete files
suite 'delete', (suite,test) ->
test 'delete last document', (done) ->
responseData = [files.pop()]
requestData = {}
requestWithCheck('delete', 'collection/documents/posts/test-3.html.md', requestData, responseData, done)
test 'check listing', (done) ->
responseData = files
requestData = {}
requestWithCheck('get', 'collection/documents/', requestData, responseData, done)
# Update files
suite 'update', (suite,test) ->
test 'update last document', (done) ->
file = files[files.length-1]
file.meta.title = 'hello WORLD'
responseData = file
requestData = file.meta
requestWithCheck('post', 'collection/documents/posts/test-2.html', requestData, responseData, done)
test 'check listing', (done) ->
responseData = files
requestData = {}
requestWithCheck('get', 'collection/documents/', requestData, responseData, done)
# Configuration
suite 'configuration', (suite, test) ->
# Set readonly config option
setup = (test, complete) ->
pluginConfig.readonly = true
complete()
# Enable default REST behaviour
tearDown = (test, complete) ->
pluginConfig.readonly = false
complete()
# Unauthorised POST test
test 'check POST fails', { before: setup, after: tearDown }, (done) ->
requestWithUnauthorizedCheck('post', done)
# Unauthorised DELETE test
test 'check DELETE fails', { before: setup, after: tearDown }, (done) ->
requestWithUnauthorizedCheck('delete', done)
# Unauthorised PUT test
test 'check PUT fails', { before: setup, after: tearDown }, (done) ->
requestWithUnauthorizedCheck('put', done)
test 'check GET is successful', { before: setup, after: tearDown }, (done) ->
responseData = files
requestData = {}
requestWithCheck('get', 'collection/documents/', requestData, responseData, done)
# Test Custom
testCustom: => @clean()