1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | var expect = require('expect.js');
|
10 | var sinon = require('sinon');
|
11 | var jade = require('jade');
|
12 | var stylus = require('stylus');
|
13 | var Promises = require('best-promise');
|
14 | var fs = require('fs-promise');
|
15 | var MiniTools = require('..');
|
16 | var bestGlobals = require('best-globals');
|
17 |
|
18 | describe('mini-tools with mocks', function(){
|
19 | describe('serveErr', function(){
|
20 | var server;
|
21 | it('should send ERR 400', function(){
|
22 | var res={};
|
23 | res.end=sinon.spy();
|
24 | res.writeHead=sinon.spy();
|
25 | var get_headersSent=sinon.stub().returns(false);
|
26 | Object.defineProperty(res,'headersSent',{get: get_headersSent});
|
27 | var err=new Error("this is the message");
|
28 | var spy_console_log=sinon.stub(console, "log");
|
29 | MiniTools.serveErr(null,res,null)(err);
|
30 | var spyed_console_log=console.log;
|
31 | spy_console_log.restore();
|
32 | expect(res.end.firstCall.args[0]).to.match(/^ERROR! \nthis is the message\n-+\nError: this is the message\n\s*at/);
|
33 | expect(get_headersSent.callCount).to.be(1);
|
34 | expect(res.end.callCount).to.be(1);
|
35 | expect(spyed_console_log.firstCall.args).to.eql(['ERROR',err]);
|
36 | expect(spyed_console_log.secondCall.args[0]).to.eql('STACK');
|
37 | expect(spyed_console_log.secondCall.args[1]).to.match(/^Error: this is the message\n\s*at/);
|
38 | expect(spyed_console_log.callCount).to.be(2);
|
39 | var length=res.writeHead.firstCall.args[1]['Content-Length'];
|
40 | expect(length).to.eql(res.end.firstCall.args[0].length);
|
41 | expect(res.writeHead.firstCall.args).to.eql([400, {
|
42 | 'Content-Length': length,
|
43 | 'Content-Type': 'text/plain; charset=utf-8'
|
44 | }]);
|
45 | expect(res.writeHead.callCount).to.be(1);
|
46 | });
|
47 | it('should not send headers if there where sent before', function(){
|
48 | var res={};
|
49 | res.end=sinon.spy();
|
50 | var get_headersSent=sinon.stub().returns(true);
|
51 | Object.defineProperty(res,'headersSent',{get: get_headersSent});
|
52 | var err=new Error("this is a message");
|
53 | var spy_console_log=sinon.stub(console, "log");
|
54 | MiniTools.serveErr(null,res,null)(err);
|
55 | var spyed_console_log=console.log;
|
56 | spy_console_log.restore();
|
57 | expect(res.end.firstCall.args[0]).to.match(/^ERROR! \nthis is a message\n-+\nError: this is a message\n\s*at/);
|
58 | expect(res.end.callCount).to.be(1);
|
59 | expect(spyed_console_log.firstCall.args).to.eql(['ERROR',err]);
|
60 | expect(spyed_console_log.secondCall.args[0]).to.eql('STACK');
|
61 | expect(spyed_console_log.secondCall.args[1]).to.match(/^Error: this is a message\n\s*at/);
|
62 | expect(spyed_console_log.callCount).to.be(2);
|
63 | });
|
64 | it('should by pass with next', function(){
|
65 | var next=sinon.spy();
|
66 | var err=new Error("next");
|
67 | var spy_console_log=sinon.stub(console, "log");
|
68 | MiniTools.serveErr(null,null,next)(err);
|
69 | var spyed_console_log=console.log;
|
70 | spy_console_log.restore();
|
71 | expect(spyed_console_log.callCount).to.be(0);
|
72 | expect(next.callCount).to.be(1);
|
73 | expect(next.firstCall.args.length).to.be(0);
|
74 | });
|
75 | it('should send ERR without headers', function(){
|
76 | var res={};
|
77 | res.end=sinon.spy();
|
78 | res.writeHead=sinon.spy();
|
79 | var err=new Error("this is the message");
|
80 | var spy_console_log=sinon.stub(console, "log");
|
81 | MiniTools.serveErr(null,res,null)(err);
|
82 | var spyed_console_log=console.log;
|
83 | spy_console_log.restore();
|
84 | expect(res.end.firstCall.args[0]).to.match(/^ERROR! \nthis is the message\n-+\nError: this is the message\n\s*at/);
|
85 | expect(res.end.callCount).to.be(1);
|
86 | expect(spyed_console_log.firstCall.args).to.eql(['ERROR',err]);
|
87 | expect(spyed_console_log.secondCall.args[0]).to.eql('STACK');
|
88 | expect(spyed_console_log.secondCall.args[1]).to.match(/^Error: this is the message\n\s*at/);
|
89 | expect(spyed_console_log.callCount).to.be(2);
|
90 | var length=res.writeHead.firstCall.args[1]['Content-Length'];
|
91 | expect(length).to.eql(res.end.firstCall.args[0].length);
|
92 | expect(res.writeHead.firstCall.args).to.eql([400, {
|
93 | 'Content-Length': length,
|
94 | 'Content-Type': 'text/plain; charset=utf-8'
|
95 | }]);
|
96 | expect(res.writeHead.callCount).to.be(1);
|
97 | });
|
98 | });
|
99 | describe("pre_eval",function(){
|
100 | var preEval=MiniTools.preEval;
|
101 | it("allow alphaless expresions", function(){
|
102 | expect(preEval("12*45+8/(3/4!)")).to.be(true);
|
103 | });
|
104 | it("reject variables", function(){
|
105 | expect(preEval("12*45+x+8/(3/4!)",{a:true},{f:true,g:true})).to.be(false);
|
106 | });
|
107 | it("reject functions", function(){
|
108 | expect(preEval("12*45+fi(8)/(3/4!)",{a:true},{f:true,g:true})).to.be(false);
|
109 | expect(preEval("12*45+fi ()/(3/4!)",{a:true},{f:true,g:true})).to.be(false);
|
110 | });
|
111 | it("accept variables and functions", function(){
|
112 | expect(preEval("name+12*45+name+8/(3/4!)-x",{name:true, x:true},{f:true,g:true})).to.be(true);
|
113 | expect(preEval("max(f(a))+12*45+a+8/(3/4!)-f(x)",{a:true, x:true},{f:true,max:true})).to.be(true);
|
114 | });
|
115 | });
|
116 |
|
117 | describe("serve-text", function(){
|
118 | it("serve utf8-normal text",function(done){
|
119 | var st=MiniTools.serveText("¡normal!");
|
120 | var res={};
|
121 | res.setHeader=sinon.spy();
|
122 | res.end=function(buf){
|
123 | expect(res.setHeader.firstCall.args).to.eql(['Content-Type', 'text/plain; charset=utf-8']);
|
124 | expect(res.setHeader.secondCall.args).to.eql(['Content-Length', 9]);
|
125 | expect(buf.toString()).to.be("¡normal!");
|
126 | done();
|
127 | };
|
128 | st(null, res);
|
129 | });
|
130 | });
|
131 | describe("stylus and jade", function(){
|
132 | function testServe(req, any, fileNameToRead, serviceName, renderizer, textType, baseDir, done){
|
133 | var stub_readFile=sinon.stub(fs,"readFile");
|
134 | stub_readFile.returns(Promises.Promise.resolve("this css ok"));
|
135 | if(renderizer===JSON){
|
136 | var stub_render=sinon.stub(renderizer, "stringify");
|
137 | stub_render.returns("this{css:ok}");
|
138 | }else{
|
139 | var stub_render=sinon.stub(renderizer, "render");
|
140 | stub_render.returns("this{css:ok}");
|
141 | }
|
142 | var res={};
|
143 | var next={};
|
144 | var stub_serveText=sinon.stub(MiniTools,"serveText",function(text, type){
|
145 | if(fileNameToRead){
|
146 | expect(stub_readFile.firstCall.args).to.eql([fileNameToRead, { encoding: 'utf8' }]);
|
147 | expect(stub_readFile.callCount).to.be(1);
|
148 | }else{
|
149 | expect(stub_readFile.callCount).to.be(0);
|
150 | }
|
151 | expect(stub_render.firstCall.args).to.eql(["this css ok"]);
|
152 | expect(stub_render.callCount).to.be(1);
|
153 | stub_readFile.restore();
|
154 | stub_render.restore();
|
155 | stub_serveText.restore();
|
156 | expect(text).to.be("this{css:ok}");
|
157 | expect(type).to.be(textType);
|
158 | return function(req1, res1){
|
159 | expect(req1).to.be(req);
|
160 | expect(res1).to.be(res);
|
161 | done();
|
162 | };
|
163 | });
|
164 | var serveThis=MiniTools[serviceName](baseDir,any);
|
165 | serveThis(req, res, next);
|
166 | }
|
167 | it("serve stylus founded file", function(done){
|
168 | var req={path:'one.css'};
|
169 | testServe(req, true, './fixtures/one.styl', "serveStylus", stylus, 'css', './fixtures', done);
|
170 | });
|
171 | it("serve jade founded file", function(done){
|
172 | var req={path:'/one'};
|
173 | testServe(req, true, 'client//one.jade', "serveJade", jade, 'html', 'client', done);
|
174 | });
|
175 | it("serve json objects", function(done){
|
176 | var req={path:'/one-object'};
|
177 | testServe(req, null, null, "serveJson", JSON, 'application/json', "this css ok", done);
|
178 | });
|
179 | it("serve double jade founded file", function(done){
|
180 | var req={path:'/one'};
|
181 | testServe(req, true, 'client//one.jade', "serveJade", jade, 'html', 'client', function(){
|
182 | testServe(req, true, 'client//one.jade', "serveJade", jade, 'html', 'client', done);
|
183 | });
|
184 | });
|
185 | it("serve specific file file", function(done){
|
186 | var req={path:'one.css'};
|
187 | testServe(req, false, 'thisFile', "serveStylus", stylus, 'css', 'thisFile', done);
|
188 | });
|
189 | var ssAny=MiniTools.serveStylus('./fixtures',true);
|
190 | it("skip non css requests", function(done){
|
191 | var req={path:'other.ext'};
|
192 | var next=done;
|
193 | var res=null;
|
194 | ssAny(req, res, next);
|
195 | });
|
196 | it("call next() if not found", function(done){
|
197 | var req={path:'inexis.css'};
|
198 | var stub_readFile=sinon.stub(fs,"readFile");
|
199 | var ErrorENOENT = new Error("ENOENT: File not found");
|
200 | ErrorENOENT.code = 'ENOENT';
|
201 | stub_readFile.throws(ErrorENOENT);
|
202 | var stub_render=sinon.stub(stylus, "render");
|
203 | var res={};
|
204 | var stub_serveText=sinon.stub(MiniTools,"serveText");
|
205 | var next=function(){
|
206 | expect(stub_readFile.callCount).to.be(1);
|
207 | expect(stub_readFile.firstCall.args).to.eql(['./fixtures/inexis.styl', { encoding: 'utf8' }]);
|
208 | expect(stub_render.callCount).to.be(0);
|
209 | expect(stub_serveText.callCount).to.be(0);
|
210 | stub_readFile.restore();
|
211 | stub_render.restore();
|
212 | stub_serveText.restore();
|
213 | done();
|
214 | };
|
215 | ssAny(req, res, next);
|
216 | });
|
217 | it("serve Error if other Error ocurs", function(done){
|
218 | var req={path:'with-bad-content.css'};
|
219 | var stub_readFile=sinon.stub(fs,"readFile");
|
220 | var ErrorOTHER = new Error("OTHER: Error");
|
221 | ErrorOTHER.code = 'OTHER';
|
222 | stub_readFile.throws(ErrorOTHER);
|
223 | var stub_render=sinon.stub(stylus, "render");
|
224 | var res={};
|
225 | var next={};
|
226 | var stub_serveText=sinon.stub(MiniTools,"serveText");
|
227 | var stub_serveErr=sinon.stub(MiniTools,"serveErr",function(req1, res1, next1){
|
228 | return function(err){
|
229 | expect(stub_readFile.firstCall.args).to.eql(['./fixtures/with-bad-content.styl', { encoding: 'utf8' }]);
|
230 | expect(stub_readFile.callCount).to.be(1);
|
231 | stub_readFile.restore();
|
232 | stub_render.restore();
|
233 | stub_serveText.restore();
|
234 | stub_serveErr.restore();
|
235 | expect(req1).to.be(req);
|
236 | expect(next1).to.be(next);
|
237 | expect(err).to.be(ErrorOTHER);
|
238 | done();
|
239 | };
|
240 | });
|
241 | ssAny(req, res, next);
|
242 | });
|
243 | });
|
244 | });
|
245 |
|
246 | var request = require('supertest');
|
247 |
|
248 | describe("mini-tools with fake server",function(){
|
249 | it("serve simple jade double request with any=false",function(done){
|
250 | var server = createServer('test/fixtures/simple',false);
|
251 | var agent=request(server);
|
252 | agent
|
253 | .get('/any')
|
254 | .expect('<h1>simple jade<p>for example</p></h1>')
|
255 | .end(function(err){
|
256 | if(err){
|
257 | return done(err);
|
258 | }
|
259 | agent.get('/any')
|
260 | .expect('<h1>simple jade<p>for example</p></h1>')
|
261 | .end(done);
|
262 | });
|
263 | });
|
264 | it("serve simple jade double request with any=true",function(done){
|
265 | var server = createServer('test/fixtures',true);
|
266 | var agent=request(server);
|
267 | agent
|
268 | .get('/simple')
|
269 | .expect('<h1>simple jade<p>for example</p></h1>')
|
270 | .end(function(err){
|
271 | if(err){
|
272 | return done(err);
|
273 | }
|
274 | agent.get('/simple')
|
275 | .expect('<h1>simple jade<p>for example</p></h1>')
|
276 | .end(done);
|
277 | });
|
278 | });
|
279 | });
|
280 |
|
281 | describe("fs tools", function(){
|
282 | it("must read multiple config", function(done){
|
283 | var ok="ok_content_"+Math.random();
|
284 | var bg=sinon.spy(bestGlobals, "changing");
|
285 | MiniTools.readConfig([
|
286 | 'test/fixtures/read-config1.json',
|
287 | 'test/fixtures/read-config2.yaml',
|
288 | 'test/fixtures/read-config3',
|
289 | 'test/fixtures/read-config4',
|
290 | { config2:2.5, config5:5, config6:6.5 },
|
291 | 'test/fixtures/read-config6',
|
292 | ]).then(function(cfg){
|
293 | expect(cfg).to.eql({
|
294 | config1:1,
|
295 | config2:2.5,
|
296 | config3:3,
|
297 | config4:4,
|
298 | config5:5,
|
299 | config6:6,
|
300 | });
|
301 | expect(bestGlobals.changing.callCount).to.be(6);
|
302 | expect(bestGlobals.changing.args[bestGlobals.changing.args.length-1]).to.eql([
|
303 | { config1: 1,
|
304 | config2: 2.5,
|
305 | config3: 3,
|
306 | config4: 4,
|
307 | config5: 5,
|
308 | config6: 6.5 },
|
309 | { config6: 6 }
|
310 | ]);
|
311 | }).then(done,done);
|
312 | });
|
313 | it("must control if file not found", function(done){
|
314 | MiniTools.readConfig([
|
315 | 'test/fixtures/read-config0',
|
316 | ]).then(function(){
|
317 | done(new Error("must fail"));
|
318 | },function(err){
|
319 | expect(err.message).to.match(/Config file does not found/);
|
320 | done();
|
321 | }).catch(done);
|
322 | });
|
323 | it("must control parameter types", function(done){
|
324 | MiniTools.readConfig([
|
325 | [],
|
326 | ]).then(function(){
|
327 | done(new Error("must fail"));
|
328 | },function(err){
|
329 | expect(err.message).to.match(/readConfig must receive string filename or config object/);
|
330 | done();
|
331 | }).catch(done);
|
332 | });
|
333 | });
|
334 |
|
335 | var express = require('express');
|
336 |
|
337 | function createServer(dir, opts, fn) {
|
338 | var _serve = MiniTools.serveJade(dir, opts);
|
339 | var app = express();
|
340 | app.listen();
|
341 | app.use(_serve);
|
342 | return app;
|
343 | }
|