1 var vows = require('vows')
2 , request = require('request')
3 , assert = require('assert')
4 , static = require('../../lib/node-static');
6 var fileServer = new static.Server(__dirname + '/../fixtures');
7 var suite = vows.describe('node-static');
9 var TEST_SERVER = 'http://localhost:' + TEST_PORT;
10 var version = static.version.join('.');
15 'requesting headers': {
17 request.head(TEST_SERVER + '/index.html', this.callback);
21 headers['requesting headers']['should respond with node-static/' + version] = function(error, response, body){
22 assert.equal(response.headers['server'], 'node-static/' + version);
26 'once an http server is listening with a callback': {
28 server = require('http').createServer(function (request, response) {
29 fileServer.serve(request, response, function(err, result) {
31 callback(request, response, err, result);
35 }).listen(TEST_PORT, this.callback)
37 'should be listening' : function(){
38 /* This test is necessary to ensure the topic execution.
39 * A topic without tests will be not executed */
44 'streaming a 404 page': {
46 callback = function(request, response, err, result) {
48 response.writeHead(err.status, err.headers);
49 setTimeout(function() {
50 response.end('Custom 404 Stream.')
54 request.get(TEST_SERVER + '/not-found', this.callback);
56 'should respond with 404' : function(error, response, body){
57 assert.equal(response.statusCode, 404);
59 'should respond with the streamed content': function(error, response, body){
61 assert.equal(body, 'Custom 404 Stream.');
65 'once an http server is listening without a callback': {
68 server = require('http').createServer(function (request, response) {
69 fileServer.serve(request, response);
70 }).listen(TEST_PORT, this.callback)
72 'should be listening' : function(){
73 /* This test is necessary to ensure the topic execution.
74 * A topic without tests will be not executed */
79 'requesting a file not found': {
81 request.get(TEST_SERVER + '/not-found', this.callback);
83 'should respond with 404' : function(error, response, body){
84 assert.equal(response.statusCode, 404);
89 'requesting a malformed URI': {
91 request.get(TEST_SERVER + '/a%AFc', this.callback);
93 'should respond with 400': function(error, response, body){
94 assert.equal(response.statusCode, 400);
99 'serving empty.css': {
101 request.get(TEST_SERVER + '/empty.css', this.callback);
103 'should respond with 200' : function(error, response, body){
104 assert.equal(response.statusCode, 200);
106 'should respond with text/css': function(error, response, body){
107 assert.equal(response.headers['content-type'], 'text/css');
109 'should respond with empty string': function(error, response, body){
110 assert.equal(body, '');
115 'serving hello.txt': {
117 request.get(TEST_SERVER + '/hello.txt', this.callback);
119 'should respond with 200' : function(error, response, body){
120 assert.equal(response.statusCode, 200);
122 'should respond with text/plain': function(error, response, body){
123 assert.equal(response.headers['content-type'], 'text/plain');
125 'should respond with hello world': function(error, response, body){
126 assert.equal(body, 'hello world');
130 'serving first 5 bytes of hello.txt': {
133 url: TEST_SERVER + '/hello.txt',
138 request.get(options, this.callback);
140 'should respond with 206' : function(error, response, body){
141 assert.equal(response.statusCode, 206);
143 'should respond with text/plain': function(error, response, body){
144 assert.equal(response.headers['content-type'], 'text/plain');
146 'should have content-length of 5 bytes': function(error, response, body){
147 assert.equal(response.headers['content-length'], 5);
149 'should have a valid Content-Range header in response': function(error, response, body){
150 assert.equal(response.headers['content-range'], 'bytes 0-4/11');
152 'should respond with hello': function(error, response, body){
153 assert.equal(body, 'hello');
157 'serving last 5 bytes of hello.txt': {
160 url: TEST_SERVER + '/hello.txt',
162 'Range': 'bytes=6-10'
165 request.get(options, this.callback);
167 'should respond with 206' : function(error, response, body){
168 assert.equal(response.statusCode, 206);
170 'should respond with text/plain': function(error, response, body){
171 assert.equal(response.headers['content-type'], 'text/plain');
173 'should have content-length of 5 bytes': function(error, response, body){
174 assert.equal(response.headers['content-length'], 5);
176 'should have a valid Content-Range header in response': function(error, response, body){
177 assert.equal(response.headers['content-range'], 'bytes 6-10/11');
179 'should respond with world': function(error, response, body){
180 assert.equal(body, 'world');
184 'serving all from the start of hello.txt': {
187 url: TEST_SERVER + '/hello.txt',
192 request.get(options, this.callback);
194 'should respond with 206' : function(error, response, body){
195 assert.equal(response.statusCode, 206);
197 'should respond with text/plain': function(error, response, body){
198 assert.equal(response.headers['content-type'], 'text/plain');
200 'should have content-length of 11 bytes': function(error, response, body){
201 assert.equal(response.headers['content-length'], 11);
203 'should have a valid Content-Range header in response': function(error, response, body){
204 assert.equal(response.headers['content-range'], 'bytes 0-10/11');
206 'should respond with "hello world"': function(error, response, body){
207 assert.equal(body, 'hello world');
211 'serving directory index': {
213 request.get(TEST_SERVER, this.callback);
215 'should respond with 200' : function(error, response, body){
216 assert.equal(response.statusCode, 200);
218 'should respond with text/html': function(error, response, body){
219 assert.equal(response.headers['content-type'], 'text/html');
223 'serving index.html from the cache': {
225 request.get(TEST_SERVER + '/index.html', this.callback);
227 'should respond with 200' : function(error, response, body){
228 assert.equal(response.statusCode, 200);
230 'should respond with text/html': function(error, response, body){
231 assert.equal(response.headers['content-type'], 'text/html');
235 'requesting with If-None-Match': {
238 request.get(TEST_SERVER + '/index.html', function(error, response, body){
241 uri: TEST_SERVER + '/index.html',
242 headers: {'if-none-match': response.headers['etag']}
247 'should respond with 304' : function(error, response, body){
248 assert.equal(response.statusCode, 304);
251 'requesting with If-None-Match and If-Modified-Since': {
254 request.get(TEST_SERVER + '/index.html', function(error, response, body){
255 var modified = Date.parse(response.headers['last-modified']);
256 var oneDayLater = new Date(modified + (24 * 60 * 60 * 1000)).toUTCString();
257 var nonMatchingEtag = '1111222233334444';
260 uri: TEST_SERVER + '/index.html',
262 'if-none-match': nonMatchingEtag,
263 'if-modified-since': oneDayLater
269 'should respond with a 200': function(error, response, body){
270 assert.equal(response.statusCode, 200);
277 request.post(TEST_SERVER + '/index.html', this.callback);
279 'should respond with 200' : function(error, response, body){
280 assert.equal(response.statusCode, 200);
282 'should not be empty' : function(error, response, body){
283 assert.isNotEmpty(body);
290 request.head(TEST_SERVER + '/index.html', this.callback);
292 'should respond with 200' : function(error, response, body){
293 assert.equal(response.statusCode, 200);
295 'head must has no body' : function(error, response, body){
296 assert.isEmpty(body);
302 'addings custom mime types': {
304 static.mime.define({'application/font-woff': ['woff']});
307 'should add woff' : function(error, response, body){
308 assert.equal(static.mime.lookup('woff'), 'application/font-woff');
313 'serving subdirectory index': {
315 request.get(TEST_SERVER + '/there/', this.callback); // with trailing slash
317 'should respond with 200' : function(error, response, body){
318 assert.equal(response.statusCode, 200);
320 'should respond with text/html': function(error, response, body){
321 assert.equal(response.headers['content-type'], 'text/html');
326 'redirecting to subdirectory index': {
328 request.get({ url: TEST_SERVER + '/there', followRedirect: false }, this.callback); // without trailing slash
330 'should respond with 301' : function(error, response, body){
331 assert.equal(response.statusCode, 301);
333 'should respond with location header': function(error, response, body){
334 assert.equal(response.headers['location'], '/there/'); // now with trailing slash
336 'should respond with empty string body' : function(error, response, body){
337 assert.equal(body, '');
342 'requesting a subdirectory (with trailing slash) not found': {
344 request.get(TEST_SERVER + '/notthere/', this.callback); // with trailing slash
346 'should respond with 404' : function(error, response, body){
347 assert.equal(response.statusCode, 404);
352 'requesting a subdirectory (without trailing slash) not found': {
354 request.get({ url: TEST_SERVER + '/notthere', followRedirect: false }, this.callback); // without trailing slash
356 'should respond with 404' : function(error, response, body){
357 assert.equal(response.statusCode, 404);
361 'once an http server is listening with custom index configuration': {
365 fileServer = new static.Server(__dirname + '/../fixtures', { indexFile: "hello.txt" });
367 server = require('http').createServer(function (request, response) {
368 fileServer.serve(request, response);
369 }).listen(TEST_PORT, this.callback)
371 'should be listening' : function(){
372 /* This test is necessary to ensure the topic execution.
373 * A topic without tests will be not executed */
378 'serving custom index file': {
380 request.get(TEST_SERVER + '/', this.callback);
382 'should respond with 200' : function(error, response, body){
383 assert.equal(response.statusCode, 200);
385 'should respond with empty string': function(error, response, body){
386 assert.equal(body, 'hello world');