рдиреЛрдбрдЬ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛

рдкрд┐рдЫрд▓реА рдмрд╛рд░ рдореИрдВрдиреЗ рдлреНрд░реЗрдорд╡рд░реНрдХ рдФрд░ рдЬреЗрдб рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рдЯреЗрдореНрдкрд▓реЗрдЯ рдЗрдВрдЬрди рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХреНрд╕рдкреНрд░реЗрд╕рдЬреЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдиреЛрдбрдЬ рдкрд░ рдПрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд▓рд┐рдЦрд╛ рдерд╛ред рдЗрд╕ рдмрд╛рд░ рдореИрдВ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдХреЗ рдкрд░реАрдХреНрд╖рдг рдкрд░ рдзреНрдпрд╛рди рджреЗрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред

рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ:
- рдореЛрдЪрд╛ - рдПрдХ рдврд╛рдВрдЪрд╛ рдЬреЛ рдЖрдкрдХреЛ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдиреЗ рдФрд░ рдЖрд╕рд╛рдиреА рд╕реЗ рдФрд░ рд╕рд░рд▓рддрд╛ рд╕реЗ рдЪрд▓рд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рд╡рд┐рднрд┐рдиреНрди рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдореЗрдВ рд░рд┐рдкреЛрд░реНрдЯ рддреИрдпрд╛рд░ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдпрд╣ рднреА рдЬрд╛рдирддрд╛ рд╣реИ рдХрд┐ рдкрд░реАрдХреНрд╖рдгреЛрдВ рд╕реЗ рдкреНрд░рд▓реЗрдЦрди рдХреИрд╕реЗ рдмрдирд╛рдпрд╛ рдЬрд╛рдПред
- "рдЕрдиреБрдореЛрджрди" рдХреА рд╢реИрд▓реА рдореЗрдВ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП (рд╕рд╣реА рдирд╛рдо рдирд╣реАрдВ рдорд┐рд▓рд╛)
- SuperTest - рдиреЛрдбрдЬ рдкрд░ HTTP рд╕рд░реНрд╡рд░ рдХреЗ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдПрдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп
- jscoverage - рдкрд░реАрдХреНрд╖рдгреЛрдВ рджреНрд╡рд╛рд░рд╛ рдХреЛрдб рдХрд╡рд░реЗрдЬ рдХрд╛ рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП



рдореИрдВрдиреЗ рдЦрд░реЛрдВрдЪ рд╕реЗ рд╕рдм рдХреБрдЫ рдирд╣реАрдВ рд▓рд┐рдЦрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдкрд░реАрдХреНрд╖рдг рдореЗрдВ рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рд╕реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рд▓рдкреЗрдЯрдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛, рдЗрд╕реЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдРрдк 2 рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рдХреЙрдкреА рдХрд┐рдпрд╛ред

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ рдкреИрдХреЗрдЬ.рдЬреЙрди рдлрд╝рд╛рдЗрд▓ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдореЙрдбреНрдпреВрд▓ рдЬреЛрдбрд╝реЗрдВред рд╣рдореЗрдВ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА: рдореЛрдЪрд╛, рдЪрд╛рд╣рд┐рдП, рд╕реБрдкрд░рдЯреЗрд╕реНрдЯред
package.json
{ "name": "app2", "version": "0.0.0", "author": "Evgeny Reznichenko <kusakyky@gmaill.com>", "dependencies": { "express": "3", "jade": "*", "should": "*", "mocha": "*", "supertest": "*" } } 

рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рдореЙрдбреНрдпреВрд▓ рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП npm i рдХрдорд╛рдВрдб рдЪрд▓рд╛рдПрдБред
рдФрд░ jscoverage рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ (Ubuntu sudo apt-get install jscoverage рдХреЗ рддрд╣рдд )ред

рдЗрд╕рдХреЗ рдмрд╛рдж, рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рд░реВрдЯ рдореЗрдВ рд▓рд┐рдмрд░реА рдбрд╛рдЗрд░реЗрдХреНрдЯрд░реА рдмрдирд╛рдПрдВ рдФрд░ рд╣рдорд╛рд░реЗ рдРрдк рдХреЛ рдХреЙрдкреА рдХрд░реЗрдВред рд╡рд╣рд╛рдВ, рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдХрд┐ рдХрд╡рд░реЗрдЬ рдЯреЗрд╕реНрдЯ рдХреЗ рд╕рд╛рде рд╕рднреА рд▓рд┐рдкрд┐рдпреЛрдВ рдХреЛ рдЖрд╕рд╛рдиреА рд╕реЗ рдХрд╡рд░ рдХрд┐рдпрд╛ рдЬрд╛рдПред
рд╣рдо app.js рдлрд╝рд╛рдЗрд▓ рдХреЛ рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВрдЧреЗ рддрд╛рдХрд┐ рдпрд╣ рд╣рдорд╛рд░реЗ рд╕рд░реНрд╡рд░ рдХреЛ рдирд┐рд░реНрдпрд╛рдд рдХрд░реЗ, рдФрд░ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рд░реВрдЯ рдореЗрдВ index.js рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдП, рдЬреЛ рд╕рд░реНрд╡рд░ рд╕реЗ рдХрдиреЗрдХреНрдЯ рд╣реЛ рдФрд░ рдЗрд╕реЗ рд╕реЙрдХреЗрдЯ рдкрд░ рд▓рдЯрдХрд╛рдПред рдФрд░ рд╡рд┐рдЪрд╛рд░реЛрдВ рдФрд░ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛рдУрдВ рдХреЗ рдкрде рдХреЛ рд╕рд╣реА рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордд рднреВрд▓рдирд╛ред
рдпрд╣ рдЗрд╕ рддрд░рд╣ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП:
index.js
 var app = require('./lib/app.js'); app.listen(3000); 


lib / app.js
 var express = require('express'), jade = require('jade'), fs = require('fs'), app = express(), viewOptions = { compileDebug: false, self: true }; //data var db = { users: [ { id: 0, name: 'Jo', age: 20, sex: 'm' }, { id: 1, name: 'Bo', age: 19, sex: 'm' }, { id: 2, name: 'Le', age: 18, sex: 'w' }, { id: 10, name: 'NotFound', age: 18, sex: 'w' } ], titles: { '/users': ' ', '/users/profile': ' ' } }; //utils function merge(a, b) { var key; if (a && b) { for (key in b) { a[key] = b[key]; } } return a; } //App settings app.set('views', __dirname + '/../views'); app.set('view engine', 'jade'); app.set('title', ' '); app.locals.compileDebug = viewOptions.compileDebug; app.locals.self = viewOptions.self; app.use(express.static(__dirname + '/../public')); app.use(app.router); app.use(function (req, res, next) { next('not found'); }); //error app.use(function (err, req, res, next) { if (/not found/i.test(err)) { res.locals.title = '  :('; res.render('/errors/notfound'); } else { res.locals.title = ''; res.render('/errors/error'); } }); app.use(express.errorHandler()); //routes //  app.all('*', function replaceRender(req, res, next) { var render = res.render, view = req.path.length > 1 ? req.path.substr(1).split('/'): []; res.render = function(v, o) { var data, title = res.locals.title; res.render = render; res.locals.title = app.get('title') + (title ? ' - ' + title: ''); //         //  if ('string' === typeof v) { if (/^\/.+/.test(v)) { view = v.substr(1).split('/'); } else { view = view.concat(v.split('/')); } data = o; } else { data = v; } // res.locals      //     (res.locals.title) data = merge(data || {}, res.locals); if (req.xhr) { //     json res.json({ data: data, view: view.join('.') }); } else { //   ,    // (   history api) data.state = JSON.stringify({ data: data, view: view.join('.') }); //    .       . view[view.length - 1] = '_' + view[view.length - 1]; //   res.render(view.join('/'), data); } }; next(); }); //   app.all('*', function loadPageTitle(req, res, next) { res.locals.title = db.titles[req.path]; next(); }); app.get('/', function(req, res){ res.render('index'); }); app.get('/users', function(req, res){ var data = { users: db.users }; res.render('index', data); }); app.get('/users/profile', function(req, res, next){ var user = db.users[req.query.id], data = { user: user }; if (user) { res.render(data); } else { next('Not found'); } }); // function loadTemplate(viewpath) { var fpath = app.get('views') + viewpath, str = fs.readFileSync(fpath, 'utf8'); viewOptions.filename = fpath; viewOptions.client = true; return jade.compile(str, viewOptions).toString(); } app.get('/templates', function(req, res) { var str = 'var views = { ' + '"index": (function(){ return ' + loadTemplate('/index.jade') + ' }()),' + '"users.index": (function(){ return ' + loadTemplate('/users/index.jade') + ' }()),' + '"users.profile": (function(){ return ' + loadTemplate('/users/profile.jade') + ' }()),' + '"errors.error": (function(){ return ' + loadTemplate('/errors/error.jade') + ' }()),' + '"errors.notfound": (function(){ return ' + loadTemplate('/errors/notfound.jade') + ' }())' + '};' res.set({ 'Content-type': 'text/javascript' }).send(str); }); module.exports = app; 



рдЖрдЗрдП app.js рдлрд╝рд╛рдЗрд▓ рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ, рддреАрди рддрд╛рд░реНрдХрд┐рдХ рднрд╛рдЧреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрди рд╕реНрдкрд╖реНрдЯ рд╣реИ:
- рдкрд╣рд▓реЗ рднрд╛рдЧ рдореЗрдВ рд╣рдо рдбреЗрдЯрд╛ рдореЙрдбрд▓ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рдкреВрд░реЗ рддрд░реНрдХ рдХреЛ рдмрд╛рд╣рд░ рдирд┐рдХрд╛рд▓реЗрдВрдЧреЗ
- рджреВрд╕рд░реЗ рднрд╛рдЧ рдореЗрдВ, рд╕рднреА рд╕рд╣рд╛рдпрдХ рдЙрдкрдпреЛрдЧрд┐рддрд╛рдУрдВ, рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреЗрд╡рд▓ рдорд░реНрдЬ рдлрд╝рдВрдХреНрд╢рди рд╣реИ
- рддреАрд╕рд░реЗ рдореЗрдВ рд╕рд░реНрд╡рд░ рд╣реА рд╣реЛрдЧрд╛

рд╣рдордиреЗ рдЕрдкрдиреА рдЗрдЪреНрдЫрд╛рдУрдВ рдкрд░ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ рд╣реИ, рдЪрд▓реЛ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдирд╛ рд╢реБрд░реВ рдХрд░реЗрдВ, рдмрд╕ рдкрд╣рд▓реЗ рдЪрд▓ рд░рд╣реЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреА рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдореЗрдХрдлрд╛рдЗрд▓ рд▓рд┐рдЦреЗрдВ рдФрд░ рдЗрд╕реЗ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреА рдЬрдбрд╝ рдореЗрдВ рд░рдЦреЗрдВред
makefile
 MOCHA = ./node_modules/.bin/mocha test: @NODE_ENV=test $(MOCHA) \ -r should \ -R spec .PHONY: test 


- -r - рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдореЛрдЪрд╛ рдХреЛ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП
- -R - рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рд╣рдо рдХрд┐рд╕ рд░реВрдк рдореЗрдВ рдкрд░реАрдХреНрд╖рдг рд░рд┐рдкреЛрд░реНрдЯ рджреЗрдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдХрдИ рдкреНрд░рдХрд╛рд░ рдХреА рд░рд┐рдкреЛрд░реНрдЯреЗрдВ рд╣реИрдВ, рдпрд╣ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧреА:
рдЪрд┐рддреНрд░



рдкрд░реАрдХреНрд╖рдг "рдЙрдкрдХрд░рдг"

рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ, рдореЛрдЪрд╛ рдкрд░реАрдХреНрд╖рдг рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рд╕реЗ рдкрд░реАрдХреНрд╖рдг рдЪрд▓рд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдРрд╕реА рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдмрдирд╛рдПрдВ рдФрд░ рд╣рдорд╛рд░рд╛ рдкрд╣рд▓рд╛ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦреЗрдВред
рдФрд░ рд╣рдо рдЕрдкрдиреЗ "рдЯреВрд▓" рдХреЗ рд╕рд╛рде рдкрд░реАрдХреНрд╖рдг рд╢реБрд░реВ рдХрд░реЗрдВрдЧреЗ, рд╣рдо рдПрдХ рдЫреЛрдЯреА рдпреЛрдЬрдирд╛ рддреИрдпрд╛рд░ рдХрд░реЗрдВрдЧреЗред
- "рдЙрдкрдХрд░рдг" рдореЗрдВ рдПрдХ рдорд░реНрдЬ рдлрд╝рдВрдХреНрд╢рди рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП
- рдорд░реНрдЬ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рджреЛ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЛ рдПрдХ рдореЗрдВ рдорд░реНрдЬ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП
- рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЬрд┐рд╕ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдкрд╣рд▓реЗ рдкреНрд░рд╕рд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЙрд╕реЗ рджреВрд╕рд░реА рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП
- рдлрд╝рдВрдХреНрд╢рди рдХреЛ рджреВрд╕рд░реА рдСрдмреНрдЬреЗрдХреНрдЯ рдирд╣реАрдВ рдмрджрд▓рдирд╛ рдЪрд╛рд╣рд┐рдП

рдореЛрдЪрд╛ рдХрд╛ BDD рдкрд░реАрдХреНрд╖рдг рд╡рд░реНрдгрди () рдмреНрд▓реЙрдХ рд╕реЗ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ ; рдкрд░реАрдХреНрд╖рдг рд╕реНрд╡рдпрдВ рдЗрд╕рдореЗрдВ рд▓рд┐рдЦреЗ рдЧрдП рд╣реИрдВ () рдмреНрд▓реЙрдХ ; рдЙрдиреНрд╣реЗрдВ рд╡рд░реНрдгрди () рдмреНрд▓реЙрдХ рдХреЗ рдЕрдВрджрд░ рд╕реНрдерд┐рдд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рд╡рд░реНрдгрди рдХреЗ рдХрд┐рд╕реА рднреА рдШреЛрдВрд╕рд▓реЗ рдХреЗ рд╢рд┐рдХрд╛рд░ () рдПрдХ рджреВрд╕рд░реЗ рдореЗрдВ рдмреНрд▓реЙрдХ рдХреА рдЕрдиреБрдорддрд┐ рд╣реИред рд╣реБрдХ рднреА рдЙрдкрд▓рдмреНрдз рд╣реИрдВ: рдкрд╣рд▓реЗ (), рдХреЗ рдмрд╛рдж (), рдкрд╣рд▓реЗ (), рдФрд░ рдмрд╛рдж ()ред рд╣реБрдХ рдХреЛ рд╡рд░реНрдгрди () рдмреНрд▓реЙрдХ рдХреЗ рдЕрдВрджрд░ рднреА рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЬрдм рд╣рдо рдПрдХ рдирдХрд▓реА рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рдореЙрдбрд▓ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдореИрдВ рдЖрдкрдХреЛ рд╣реБрдХ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдмрддрд╛рдКрдВрдЧрд╛

рдкрд░реАрдХреНрд╖рдг рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ, tools.js рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдВ рдФрд░ tools.merge рдХреЗ рд▓рд┐рдП рдПрдХ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦреЗрдВред
рдкрд░реАрдХреНрд╖рдг / рдЙрдкрдХрд░рдгред js
 var tools = require('../lib/tools/index.js'); describe('tools', function () { // ""    merge it('should be have #merge', function () { tools.should.be.have.property('merge'); tools.merge.should.be.a('function'); }); describe('#merge', function () { // merge       it('should merged', function () { var a = { foo: '1' }, b = { bar: '2' }; tools.merge(a, b).should.eql({ foo: '1', bar: '2' }); }); //      ,   it('should be extend', function () { var a = { foo: '1' }, b = { bar: '2' }; tools.merge(a, b); //   ,    //     a.should.not.equal({ foo: '1', bar: '2' }); a.should.equal(a); }); //      it('should not be extended', function () { var a = { foo: '1' }, b = { bar: '2' }; tools.merge(a, b); b.should.not.eql({ foo: '1', bar: '2' }); }); }); }); 


рдпрджрд┐ рд╣рдо рдЕрдм рдкрд░реАрдХреНрд╖рдг рдЪрд▓рд╛рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдЙрдкрдХрд░рдг рдореЙрдбреНрдпреВрд▓ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рдЪрд░рдг рдореЗрдВ рдЧрд▓рддреА рд╕реЗ рдЧрд┐рд░ рдЬрд╛рдПрдВрдЧреЗ, рдЬреЛ рд╕рд╛рдорд╛рдиреНрдп рд╣реИ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдпрд╣ рдореЙрдбреНрдпреВрд▓ рдЕрднреА рддрдХ рдирд╣реАрдВ рд╣реИред рдПрдХ рдлрд╝рд╛рдЗрд▓ lib / рдЙрдкрдХрд░рдг / index.js рдмрдирд╛рдПрдБ рдФрд░ рд╡рд╣рд╛рдБ lib / app.js рд╕реЗ рдорд░реНрдЬ рдлрд╝рдВрдХреНрд╢рди рдХреЛрдб рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░реЗрдВред
рдореЗрдХ рдЯреЗрд╕реНрдЯ рдЪрд▓рд╛рдПрдВ рдФрд░ рджреЗрдЦреЗрдВ рдХрд┐ рд╕рднреА рдЪрд╛рд░ рдкрд░реАрдХреНрд╖рдг рдЕрднрд┐рднреВрдд рд╣реИрдВ,
рдЪрд┐рддреНрд░


рдХреНрдпреЛрдВрдХрд┐ рдкрд╣рд▓реЗ рдкрд░реАрдХреНрд╖рдг рд╕реЗ рдЕрднрд┐рднреВрдд рд╣реИ, рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдорд░реНрдЬ рдлрд╝рдВрдХреНрд╢рди рдЙрдкрдХрд░рдг рдореЙрдбреНрдпреВрд▓ рд╕реЗ рдирд┐рд░реНрдпрд╛рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдирд┐рд░реНрдпрд╛рдд рдЬреЛрдбрд╝реЗрдВ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдлрд┐рд░ рд╕реЗ рдЪрд▓рд╛рдПрдВ, рдЕрдм рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

рдмрд╛рдХреА рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдЖрдЧреЗ рдХреЗ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдХрд╡рд░реЗрдЬ рдЯреЗрд╕реНрдЯ рдЬреЛрдбрд╝реЗрдВред
рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдЪрд▓рдиреЗ рд╡рд╛рд▓рд╛ jscoverage рдЬреЛрдбрд╝реЗрдВ --encoding = utf8 рдФрд░ --no-highlight , рдЖрдиреЗ рд╡рд╛рд▓реА рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рдореЗрдЪреНрдЫрд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░реЗрдВ, рдФрд░ рдирд┐рд╡рд░реНрддрдорд╛рди рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреЗ рд░реВрдк рдореЗрдВ lib-cov ред рдЕрдм рд╣рдо рдХрд╡рд░реЗрдЬ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдореЛрдЪрд╛ рд▓реЙрдиреНрдЪ рдХреЛ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рдкрд░реНрдпрд╛рд╡рд░рдг рдЪрд░ COVERAGE = 1 рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдХрд╡рд░реЗрдЬ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд╕реБрдВрджрд░ HTML рдкреГрд╖реНрда рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд░рд┐рдкреЛрд░реНрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ HTML-cov рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддреЗ рд╣реИрдВред
makefile
 MOCHA = ./node_modules/.bin/mocha test: @NODE_ENV=test $(MOCHA) \ -r should \ -R spec test-cov: lib-cov @COVERAGE=1 $(MOCHA) \ -r should \ -R html-cov > coverage.html lib-cov: clear @jscoverage --encoding=utf8 --no-highlight lib lib-cov clear: @rm -rf lib-cov coverage.html .PHONY: test test-cov clear 


рдЖрдЗрдП рдЕрдкрдиреЗ рдкрд░реАрдХреНрд╖рдг рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рдПрдВ рдФрд░ рдкрдВрдХреНрддрд┐ рдХреЛ рд╕рдмрд╕реЗ рдКрдкрд░ рд░рдЦреЗрдВ:
 var tools = require('../lib/tools/index.js'); 

рдкрд░
 var tools = process.env.COVERAGE ? require('../lib-cov/tools/index.js') : require('../lib/tools/index.js'); 

рд╡рд╣ рд╕рдм рд╣реИред рдЕрдм рд╣рдо рдЯреЗрд╕реНрдЯ-рдХреЛрд╡ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред рдХрд╡рд░реЗрдЬ рдХреА рдлрд╝рд╛рдЗрд▓ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд░реВрдЯ рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрддреА рд╣реИ, рдХрд╡рд░реЗрдЬ рдЯреЗрд╕реНрдЯ рдХреЗ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЗ рд╕рд╛рде, рдлрд╝рд╛рдЗрд▓ рдЖрддреНрдордирд┐рд░реНрднрд░ рд╣реИ рдФрд░ рдЗрд╕реЗ рддреБрд░рдВрдд рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдЦреЛрд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдЪрд┐рддреНрд░


рдЬрд┐рди рд▓рд╛рдЗрдиреЛрдВ рдореЗрдВ рдПрдХ рднреА рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдирд╣реАрдВ рдереА, рдЙрдиреНрд╣реЗрдВ рд▓рд╛рд▓ рд░рдВрдЧ рдореЗрдВ рджрд┐рдЦрд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдпрд╣ рд╕реНрдерд╛рди рдкрд░реАрдХреНрд╖рдгреЛрдВ рд╕реЗ рдврдВрдХрд╛ рдирд╣реАрдВ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдлрд╝рд╛рдЗрд▓ рдХреЗ рдкреНрд░рддрд┐рд╢рдд рдХреЗ рд░реВрдк рдореЗрдВ рдкрд░реАрдХреНрд╖рдг рдХрд╡рд░реЗрдЬ рдХреЗ рд╕рд╛рдорд╛рдиреНрдп рдЖрдБрдХрдбрд╝реЗ рднреА рдкреНрд░рджрд╛рди рдХрд┐рдП рдЧрдП рд╣реИрдВред

рдЦреИрд░, рдкрд░реАрдХреНрд╖рдг рд╡рд╛рддрд╛рд╡рд░рдг рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдпрд╣ рдбреЗрдЯрд╛рдмреЗрд╕ рдФрд░ рд╕рд░реНрд╡рд░ рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдмрдирд╛ рд╣реБрдЖ рд╣реИред

рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд╕рд╛рде рдкрд░реАрдХреНрд╖рдг рдХрд╛рд░реНрдп

рд╣рдо рдЕрдкрдиреЗ рдореЙрдбрд▓реЛрдВ рдХреЗ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдПрдХ рдХреЛрдб рд▓рд┐рдЦреЗрдВрдЧреЗред рдкрд╣рд▓реЗ, рдЪрд▓реЛ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдкрд░ рдирд┐рд░реНрдгрдп рд▓реЗрддреЗ рд╣реИрдВред
1) рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рджреЛ рдореЙрдбрд▓ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реВрдЪреА рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП
2) рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдореЙрдбрд▓ рдореЗрдВ рд╡рд┐рдзрд┐рдпрд╛рдБ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП:
- рдвреВрдВрдвреЗрдВ - рдлрд╝рдВрдХреНрд╢рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреА рдПрдХ рд╕реВрдЪреА рд▓реМрдЯрд╛рддрд╛ рд╣реИ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░рдХрд╛рд░ рдХреА рдПрдХ рд╡рд╕реНрддреБ рдХреЗ рд╕рд╛рде, рднрд▓реЗ рд╣реА рдХреБрдЫ рднреА рди рд╣реЛ
- findById - рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЖрдИрдбреА рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреА рдЦреЛрдЬ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдП рдФрд░ рдкрд░рд┐рдгрд╛рдо рдХреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдпрд╛ рдЗрд╕ рдЖрдИрдбреА рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╣реАрдВ рд╣реЛрдиреЗ рдкрд░ рдХреБрдЫ рднреА рдирд╣реАрдВ
- рд╕рд╣реЗрдЬреЗрдВ - рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рд╕рд╣реЗрдЬрдирд╛ рд╣реЛрдЧрд╛, рддреНрд░реБрдЯрд┐ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдЧрд▓рдд рд░рд┐рдЯрд░реНрди
- toJSON - рдлрд╝рдВрдХреНрд╢рди рд░рд┐рдЯрд░реНрди рдЯрд╛рдЗрдк рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛рд╕реНрдЯрд┐рдВрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП
3) рдпреВрдЬрд░рд▓рд┐рд╕реНрдЯ рдореЙрдбрд▓ рдореЗрдВ рдХреЗрд╡рд▓ toJSON рд╡рд┐рдзрд┐ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП
рдЯреЗрд╕реНрдЯ рдХреЛрдб
 var should = require('should'), db = process.env.COVERAGE ? require('../lib-cov/models/db.js') : require('../lib/models/db.js'), models = process.env.COVERAGE ? require('../lib-cov/models/index.js') : require('../lib/models/index.js'), User = models.User, UserList = models.UserList; describe('models', function () { //      //   "describe('models')" before(function () { db.regen(); }); //    User it('should be have User', function () { models.should.be.have.property('User'); models.User.should.be.a('function'); }); //    UserList it('should be have UserList', function () { models.should.be.have.property('UserList'); models.UserList.should.be.a('function'); }); //  User describe('User', function () { // User    find it('should be have #find', function () { User.should.be.have.property('find'); User.find.should.be.a('function'); }); // User    findById it('should be have #findById', function () { User.should.be.have.property('findById'); User.findById.should.be.a('function'); }); // User    save it('should be have #save', function () { User.prototype.should.be.have.property('save'); User.prototype.save.should.be.a('function'); }); // User    toJSON it('should be have #toJSON', function () { User.prototype.should.be.have.property('toJSON'); User.prototype.toJSON.should.be.a('function'); }); describe('#find', function () { //find   UserList it('should be instanceof UserList', function (done) { User.find(function (err, list) { if (err) return done(err); list.should.be.an.instanceOf(UserList); done(); }); }); //find   UserList,     it('should not be exist', function (done) { //  db.drop(); User.find(function (err, list) { //  db.generate(); if (err) return done(err); list.should.be.an.instanceOf(UserList); done(); }); }); }); describe('#findById', function () { //findById     User it('should be instanceof User', function (done) { User.findById(0, function (err, user) { if (err) return done(err); user.should.be.an.instanceOf(User); done(); }); }); //findById   ,     it('should not be exists', function (done) { User.findById(100, function (err, user) { if (err) return done(err); should.not.exist(user); done(); }); }); }); describe('#save', function () { //save   ,     it('should not be saved', function (done) { var user = new User({ name: 'New user', age: 0, sex: 'w' }); user.save(function (err) { err.should.eql('Invalid age'); done(); }); }); //  ,       it('should be saved', function (done) { var newuser = new User({ name: 'New user', age: 2, sex: 'w' }); newuser.save(function (err) { if (err) return done(err); User.findById(newuser.id, function (err, user) { if (err) return done(err); user.should.eql(newuser); done(); }); }); }); }); describe('#toJSON', function () { //toJSON   json   it('should be return json', function (done) { User.findById(0, function (err, user) { if (err) return done(err); user.toJSON().should.be.eql({ id: 0, name: 'Jo', age: 20, sex: 'm' }); done(); }); }); }); }); describe('UserList', function () { //UserList    toJSON it('should be have #toJSON', function () { UserList.prototype.should.be.have.property('toJSON'); UserList.prototype.toJSON.should.be.a('function'); }); }); }); 


рдХреЛрдб рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдХреЗрд╡рд▓ рдХреБрдЫ рдмрд┐рдВрджреБрдУрдВ рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░реВрдВрдЧрд╛ред
  before(function () { db.regen(); }); 

рдпрд╣ рдХреЛрдб рдкрд░реАрдХреНрд╖рдг рдХреЗ рд╢реБрд░реВ рд╣реЛрдиреЗ рдкрд░ рдПрдХ рдмрд╛рд░ рдХрд╣рд╛ рдЬрд╛рдПрдЧрд╛ред рдпрд╣рд╛рдВ рдЖрдк рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рдкрд░реАрдХреНрд╖рдг рдбреЗрдЯрд╛ рд╕реЗ рднрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдбреЗрдЯрд╛рдмреЗрд╕ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдХреЗрд╡рд▓ рд░реАрдЬрди рд╡рд┐рдзрд┐ рдХрд╣рддреЗ рд╣реИрдВ, рдЬреЛ рд╣рдорд╛рд░реЗ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЛ рдкрд░реАрдХреНрд╖рдг рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдЖрд░рдВрдн рдХрд░рддрд╛ рд╣реИред
рдпрд╣ рдЗрд╕ рддрдереНрдп рдкрд░ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рдПрдХ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд╢реИрд▓реА рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрдм рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рдмреНрд▓реЙрдХ рдкрд░реАрдХреНрд╖рдг рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдП рдЧрдП () рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдПрдХ рддреНрд░реБрдЯрд┐ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рддреНрд░реБрдЯрд┐ рдЗрд╕рдХреЗ рдкрд╛рд╕ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред рд╕реНрдкрд╖реНрдЯрддрд╛ рдХреЗ рд▓рд┐рдП рдХреЛрдб рдХрд╛ рдПрдХ рдЯреБрдХрдбрд╝рд╛:
 ... //find   UserList it('should be instanceof UserList', function (done) { User.find(function (err, list) { if (err) return done(err); list.should.be.an.instanceOf(UserList); done(); }); }); ... 


рдЕрдм рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред рдХрд╛рдордЧрд╛рд░ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ, рдореЙрдбрд▓ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдмрдирд╛рдПрдВ, рдЬрд╣рд╛рдВ рдореЙрдбрд▓ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдорд╛рд░реА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд▓рд╛рдЧреВ рдХреА рдЬрд╛рдПрдЧреА:
рдореЙрдбрд▓ / db.js
 /* *    */ //  var users = []; exports.users = users; //     exports.regen = function () { exports.drop(); exports.generate(); }; exports.drop = function () { //    , //      users.splice(0, users.length); }; exports.generate = function () { //  users.push({ id: 0, name: 'Jo', age: 20, sex: 'm' }); users.push({ id: 1, name: 'Bo', age: 19, sex: 'm' }); users.push({ id: 2, name: 'Le', age: 18, sex: 'w' }); users.push({ id: 10, name: 'NotFound', age: 18, sex: 'w' }); }; //   exports.generate(); 


рдореЙрдбрд▓ / user.js
 var util = require('util'), db = require('./db.js'), UserList = require('./userlist.js'), users = db.users; /* *   */ var User = module.exports = function User(opt) { this.id = users.length; this.name = opt.name; this.age = opt.age; this.sex = opt.sex; this.isNew = true; } /* *        */ function loadFromObj(obj) { var user = new User(obj); user.id = obj.id; user.isNew = false; return user; } /* *       */ User.find = function (fn) { var i, l = users.length, list; if (l) { list = new UserList(); for (i = 0, l; l > i; i += 1) { list.push(loadFromObj(users[i])); } } fn(null, list); }; /* *    id */ User.findById = function (id, fn) { var obj = users[id], user; if (obj) { user = loadFromObj(obj); } fn(null, user); }; /* *  */ User.prototype.save = function (fn) { var err; //    if (Number.isFinite(this.age) && this.age > 0 && this.age < 150) { if (this.isNew) { users.push(this.toJSON()); this.isNew = false; } else { users[this.id] = this.toJSON(); } } else { err = 'Invalid age'; } fn(err); }; User.prototype.toJSON = function () { var json = { id: this.id, name: this.name, age: this.age, sex: this.sex }; return json; }; 


рдореЙрдбрд▓ / userlist.js
 var util = require('util'); /* * UserList -  ,   Array */ var UserList = module.exports = function UserList() { Array.apply(this) } util.inherits(UserList, Array); UserList.prototype.toJSON = function () { var i, l = this.length, arr = new Array(l); for (i = 0; l > i; i += 1) { arr[i] = this[i].toJSON(); } return arr; }; 


рдореЙрдбрд▓ / index.js
 exports.User = require('./user.js'); exports.UserList = require('./userlist.js'); 



рд╣рдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдореЙрдбрд▓ рдХрдиреЗрдХреНрд╢рди рдХреЛ рдЬреЛрдбрд╝рдХрд░ lib / app.js рдХреЛрдб рдХреЛ рдЯреНрд╡рд┐рд╕реНрдЯ рдХрд░реЗрдВрдЧреЗ рдФрд░ рд╣рдо рдЗрд╕рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд╕рд╛рде рд╕рднреА рдХрд╛рдо рдХрд░реЗрдВрдЧреЗред
lib / app.js
 var ... User = require('./models/index.js').User, ... ... app.get('/users', function(req, res, next){ User.find(function (err, users) { if (err) { next(err); } else { res.render('index', { users: users.toJSON() }); } }); }); app.get('/users/profile', function(req, res, next){ var id = req.query.id; User.findById(id, function(err, user) { if (user) { res.render({ user: user.toJSON() }); } else { next('Not found'); } }); }); ... 



рдЖрд╡реЗрджрди рдХрд╛ рдкрд░реАрдХреНрд╖рдг

рдЕрдВрддрд┐рдо рднрд╛рдЧ рдкрд░реАрдХреНрд╖рдгреЛрдВ рджреНрд╡рд╛рд░рд╛ рдХрд╡рд░ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдпрд╣ рдПрдХ рдбрд╛рдпрд░реЗрдХреНрдЯ http рд╕рд░реНрд╡рд░ рд╣реИред рдореИрдВ рдИрдорд╛рдирджрд╛рд░реА рд╕реЗ рдорд╛рдирддрд╛ рд╣реВрдВ рдХрд┐ рдпрд╣рд╛рдВ рдореИрдВрдиреЗ рдХреЗрд╡рд▓ рдЪрд╛рд░ рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдХреЛ рд╕реНрдерд┐рд░ рдХрд░рдиреЗ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ рд╣реИ:
1) рдЙрддреНрддрд░ html рдореЗрдВ рдЖрдирд╛ рдЪрд╛рд╣рд┐рдП рдЕрдЧрд░ рдпрд╣ рдПрдХ рдирд┐рдпрдорд┐рдд рдЕрдиреБрд░реЛрдз рд╣реИ
2) рдЬрд╡рд╛рдм рдЕрдЧрд░ jjax рд╣реИ, рддреЛ рдЗрд╕реЗ json рдореЗрдВ рдЖрдирд╛ рдЪрд╛рд╣рд┐рдП
3) рд╕рд╛рдЗрдЯ рдХреЗ рд░реВрдЯ рдкрд░ рдПрдХ GET рдЕрдиреБрд░реЛрдз рдкреГрд╖реНрда / рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрд╣рд╛рдВ рд╢реАрд░реНрд╖рдХ рдореЗрдВ 'My site' рдХрд╛ рдорд╛рди рд╣реИ
рд╕реБрдкрд░рд╕реНрдЯрд╛рд░ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рдЗрд╕ рддрд░рд╣ рдХреЗ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдирд╛ рдЖрд╕рд╛рди рдФрд░ рд╕рд░рд▓ рд╣реИ:
рдкрд░реАрдХреНрд╖рдг / app.js
 var request = require('supertest'), app = process.env.COVERAGE ? require('../lib-cov/app.js') : require('../lib/app.js'); describe('Response html or json', function () { //   ,   //   html it('should be responded as html', function (done) { request(app) .get('/') .expect('Content-Type', /text\/html/) .expect(200, done); }); //  ,   json it('should be responded as json', function (done) { request(app) .get('/') .set('X-Requested-With', 'XMLHttpRequest') .expect('Content-Type', /application\/json/) .expect(200, done); }); }); describe('GET /', function () { //  title ===   it('should be included title', function (done) { request(app) .get('/') .end(function (err, res) { if (err) return done(err); res.text.should.include('<title> </title>'); done(); }); }); //  title ===   it('should be included title', function (done) { request(app) .get('/') .set('X-Requested-With', 'XMLHttpRequest') .end(function (err, res) { if (err) return done(err); res.body.should.have.property('data'); res.body.data.should.have.property('title', ' '); done(); }); }); }); 


рдЕрдиреБрд░реЛрдз () рдореЗрдВ, рд╣рдореЗрдВ http.Server рдпрд╛ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЛ рдкрд╛рд░рд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рд╕реБрдкрд░рдЯреЗрд╕реНрдЯ рд╕рд░реНрд╡рд░ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реБрдкрд░рдПрдЬреЗрдВрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрдк рд╕рд░реНрд╡рд░ рд╕реЗ рдЕрдиреБрд░реЛрдз рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕рдХреА рд╕рднреА рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЗ рд╕рддреНрдпрд╛рдкрди рдХреА рдЙрдореНрдореАрдж () рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рдпрд╛ рд╕реАрдзреЗ рд╣реИрдВрдбрд▓рд░ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП () рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдирд┐рд╖реНрдХрд░реНрд╖

рд╣рдорд╛рд░реЗ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдирд╛ рдЗрддрдирд╛ рдЖрд╕рд╛рди (рдФрд░ рдЖрд╡рд╢реНрдпрдХ рднреА) рд╣реИред рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдореЗрд░реЗ рдЫреЛрдЯреЗ рдирдореВрдиреЗ рдХреЛрдб рдореЗрдВ, рдпрд╣ рдкрд░реАрдХреНрд╖рдг рдХреЛрдб рд╕реЗ рдЕрдзрд┐рдХ рдирд┐рдХрд▓рд╛, рд▓реЗрдХрд┐рди рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдпреЗ рдкрд░реАрдХреНрд╖рдг рдкреВрд░реНрдг рдирд╣реАрдВ рд╣реИрдВ рдФрд░ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рддреНрд░реБрдЯрд┐ рдкрд░реАрдХреНрд╖рдг рджреНрд╡рд╛рд░рд╛ рдХрд╡рд░ рдирд╣реАрдВ рдХреА рдЬрд╛рддреА рд╣реИ рдЬрдм рд╣рдо рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рджреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдмрдЪрд╛рддреЗ рд╣реИрдВред рдпрджреНрдпрдкрд┐ рдХрд╡рд░реЗрдЬ рдкрд░реАрдХреНрд╖рдгреЛрдВ рд╕реЗ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдореЙрдбрд▓ рдЙрд╕ рд╕реНрдерд╛рди рдкрд░ рдкрд░реАрдХреНрд╖рдг рджреНрд╡рд╛рд░рд╛ рдХрд╡рд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдЬрд╣рд╛рдВ рдирдпрд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдмрдЪрд╛ рд╣реИред
рдЗрд╕рд▓рд┐рдП, рдкрд░реАрдХреНрд╖рдг рд╕реНрд╡рдпрдВ рдПрдХ рд░рд╛рдордмрд╛рдг рдирд╣реАрдВ рд╣реИрдВ, рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рд▓рд┐рдЦрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдЖрдкрдХреЛ рдЫреЛрдЯреА рдЪреАрдЬрд╝реЛрдВ рдХреЛ рд╕рдордЭрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдФрд░ рдЙрди рд╕реНрдерд╛рдиреЛрдВ рдХрд╛ рд╕рдЯреАрдХ рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рд╕рдорд╕реНрдпрд╛рдПрдВ рдкреИрджрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдХреЛрдб рдЬреАрдердм рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИ

Source: https://habr.com/ru/post/In162555/


All Articles