Skip to content

Commit

Permalink
Zee: Added tests around the API; Oh and this is my first commit!
Browse files Browse the repository at this point in the history
  • Loading branch information
Zee committed Feb 15, 2016
0 parents commit 9371e92
Show file tree
Hide file tree
Showing 13 changed files with 453 additions and 0 deletions.
25 changes: 25 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Logs
logs
*.log

# Runtime data
pids
*.pid
*.seed

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directory
# Deployed apps should consider commenting this line out:
# see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git
node_modules
42 changes: 42 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const express = require('express'),
path = require('path'),
favicon = require('serve-favicon'),
logger = require('morgan'),
cookieParser = require('cookie-parser'),
bodyParser = require('body-parser'),
routes = require('./routes/index');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());

app.use('/', routes);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});

// error handlers
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
});
}

app.use(function(err, req, res, next) {
res.status(err.status || 500);
});

module.exports = app;
15 changes: 15 additions & 0 deletions bin/start
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env node
'use strict';

let forever = require('forever-monitor');
var child = new (forever.Monitor)('./bin/www');

child.on('restart', function() {
console.log('Forever restarting script for ' + child.times + ' time');
});

child.on('exit:code', function(code) {
console.log('Forever detected script exited with code ' + code);
});

child.start();
90 changes: 90 additions & 0 deletions bin/www
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/usr/bin/env node

/**
* Module dependencies.
*/

var app = require('../app');
var debug = require('debug')('FamilyFriendly:server');
var http = require('http');

/**
* Get port from environment and store in Express.
*/

var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

/**
* Create HTTP server.
*/

var server = http.createServer(app);

/**
* Listen on provided port, on all network interfaces.
*/

server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

/**
* Normalize a port into a number, string, or false.
*/

function normalizePort(val) {
var port = parseInt(val, 10);

if (isNaN(port)) {
// named pipe
return val;
}

if (port >= 0) {
// port number
return port;
}

return false;
}

/**
* Event listener for HTTP server "error" event.
*/

function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}

var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;

// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}

/**
* Event listener for HTTP server "listening" event.
*/

function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
10 changes: 10 additions & 0 deletions config/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
var nconf = require('nconf');

var environment = process.env.NODE_ENV || 'local';

nconf
.argv()
.env()
.file({ file: './config/' + environment + '.json' });

module.exports = nconf;
3 changes: 3 additions & 0 deletions config/local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{

}
42 changes: 42 additions & 0 deletions helpers/moviedb-helper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use strict';
const tmdb = require('moviedb')('755ceee170d06dc11c2bd9f646014c97'),
log = require('../logger');

function getMoviesFromSearch(movieName, req) {

return new Promise((resolve, reject) => {

if(!movieName)
reject();

try {
tmdb.searchMovie({query: movieName}, function(error, response) {
resolve(response);
});
} catch (err) {
log.error({err: err}, 'Problem querying the search endpoint');
reject(new Error('Problem querying the search endpoint'));
}
});
}

function getMovieById(movieId, req) {
return new Promise((resolve, reject) => {
if(!movieId)
reject();

try {
tmdb.movieInfo({id: movieId}, function(error, response) {
resolve(response);
});
} catch (err) {
log.error({err: err}, 'Problem getting movie information by id');
reject(new Error('Problem getting movie information by id'));
}
});
}

module.exports = {
getMoviesFromSearch,
getMovieById
}
63 changes: 63 additions & 0 deletions logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
var bunyan = require('bunyan'),
package = require('./package.json'),
path = require('path');

//get from package file
var applicationName = package.name;
var logPath = path.join(__dirname,'./logs/');

var logPaths = {
fatal: logPath + applicationName + '-fatal.log',
error: logPath + applicationName + '-error.log',
warn: logPath + applicationName + '-warn.log',
info: logPath + applicationName + '-info.log'
};

var log = bunyan.createLogger({
name: applicationName,
serializers: bunyan.stdSerializers,
streams: [
{
stream: process.stdout
},
{
//"fatal" (60): The service/app is going to stop or become unusable now.
level: 'fatal',
path: logPaths.fatal,
period: '1d', // daily rotation
count: 5, // keep 5 back copies
type: 'rotating-file'
},
{
//"error" (50): Fatal for a particular request, but the service/app continues servicing other requests
level: 'error',
path: logPaths.error,
period: '1d', // daily rotation
count: 5, // keep 5 back copies
type: 'rotating-file'
},
{
//"warn" (40): A note on something that should probably be looked at by an operator eventually.
level : 'warn',
path : logPaths.warn,
period: '1d', // daily rotation
count: 5, // keep 5 back copies
type: 'rotating-file'
},
{
//"info" (30): Detail on regular operation.
level: 'info',
path: logPaths.info,
period: '1d', // daily rotation
count: 5, // keep 5 back copies
type: 'rotating-file'
}
]
});

module.exports = log;
module.exports.stream = {
write: function(message, encoding){
log.info(message);
}
}
29 changes: 29 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "FamilyFriendly",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node bin/start >> logs/forever.log",
"test": "node_modules/.bin/istanbul test ./node_modules/mocha/bin/_mocha -- specs -R spec --recursive --timeout 1000"
},
"dependencies": {
"body-parser": "~1.13.2",
"bunyan": "^1.6.0",
"cookie-parser": "~1.3.5",
"debug": "~2.2.0",
"express": "~4.9.8",
"forever-monitor": "^1.7.0",
"istanbul": "^0.4.2",
"jade": "^1.11.0",
"mocha": "^2.4.5",
"morgan": "^1.6.1",
"moviedb": "^0.2.2",
"nconf": "^0.8.4",
"nock": "^7.0.2",
"path": "^0.12.7",
"request": "^2.69.0",
"serve-favicon": "~2.3.0",
"should": "^8.2.2",
"supertest": "^1.2.0"
}
}
36 changes: 36 additions & 0 deletions routes/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const express = require('express'),
router = express.Router(),
log = require('../logger'),
movieDbService = require('../helpers/moviedb-helper');

router.get('/', function(req, res) {
res.sendStatus(200);
});

router.get('/search/:moviename', function(req, res) {

movieDbService.getMoviesFromSearch(req.params.moviename, req)
.then(movies => {
res.json(movies);
})
.catch(err => {
log.error({metaData: req.metaData, err: err}, 'An error occurred trying to retrieve movies');
});
});

router.get('/movie/:movieid', function(req, res) {
movieDbService.getMovieById(req.params.movieid, req)
.then(movie => {
res.json(movie);
})
.catch(err => {
log.error({metaData: req.metaData, err: err}, 'An error occured trying to retrieve the movie information by its id');
});
});

// TODO: implement versioning and output
router.get('/api/:version', function(req, res) {
res.send(req.params.version);
});

module.exports = router;
6 changes: 6 additions & 0 deletions specs/global-spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
require('should');
const nock = require('nock');

beforeEach(function() {
nock.cleanAll();
});
Loading

0 comments on commit 9371e92

Please sign in to comment.