hopjs
Version:
A RESTful declarative API framework, with stub generators for Shell, and Android
263 lines (207 loc) • 13.2 kB
JavaScript
/* This example is an extension of the examples/intro */
var express= require('express');
var path = require('path');
var Hop = require("./../../index");
/*
This is express boiler plate, see http://expressjs.com/guide.html
*/
var app = express();
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.urlencoded());
app.use(express.json());
app.use(express.cookieParser('your secret here'));
app.use(express.session());
app.use(function(req,res,next){
console.log(req.body);
next();
});
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
});
app.engine("jade",require('jade').__express);
app.get("/",function(req,res){
res.render("index",{Hop:Hop});
});
var users={};
var lastUserId=0;
var UserService = {}
UserService.create=function(user,onComplete){
if(!/.{3,100}/.test(user.email)){
return onComplete("Invalid email address specified: "+user.email);
}
if(!/[A-Za-z0-9]{3,100}/.test(user.name)){
return onComplete("Invalid name specified: "+user.name);
}
users[lastUserId]=user;
user.id = lastUserId;
lastUserId++;
return onComplete(null,user);
}
UserService.authenticate=function(credentials,onComplete,request){
for(var i in users){
var user = users[i];
if(user.name==credentials.name && user.password==credentials.password){
request.session.user=user;
return onComplete(null,user);
}
}
return onComplete("Permission denied");
}
UserService.del=function(input,onComplete,request){
if(users[input.id]!=undefined){
console.log("Deleted user with id:",input.id);
delete users[input.id];
return onComplete(null,true);
} else {
return onComplete(null,false);
}
}
UserService.list=function(input,onComplete){
return onComplete(null,users);
}
UserService.load=function(input,onComplete){
return onComplete(null,users[input.id]);
}
UserService.currentUser=function(input,onComplete,request){
return onComplete(null,request.session.user);
}
UserService.logout=function(input,onComplete,request){
delete request.session.user;
return onComplete(null,true);
}
Hop.defineModel("Role",function(role){
role.field("customer","Customer","The customer the user has the role on").integer().ID();
role.field("role","Role","The role the user has").string().values(["Admin","User","SuperAdmin"]);
});
Hop.defineModel("User",function(user){
user.field("id","UserID","The user's id").integer().ID();
user.field("name","Username","The user's username").string().regexp(/[A-Za-z0-9\_\-]{3,10}/,"Usernames must be between 3 and 10 characters long, and can only contain alphanumeric characters");
user.field("email","Email","The user's email address").string();
user.field("password","Password","The user's password").password();
user.field("favoriteColor","Favorite color").string().regexp(/[A-Za-z]{3,10}/,"Colors must be between 3 and 10 characters long, and can only contain characters");
user.field("roles","The roles the user has").isArray().model("Role");
user.link("self").call("UserService.load");
user.link("doc","/api/#User.model");
});
ValidatorTest={};
ValidatorTest.test=function(input,onComplete){
return onComplete(null,true);
}
ValidatorTest.test2=function(input,onComplete){
return onComplete(null,true);
}
ValidatorTest.test3=function(input,onComplete){
return onComplete(null,true);
}
ValidatorTest.test4=function(input,onComplete){
return onComplete(null,true);
}
Hop.defineModel("SubModel2",function(model){
model.field("string").string().regexp(/[A-Z]{1,4}/);
});
Hop.defineModel("SubModel1",function(model){
model.field("yetAnotherArrayOfModels").isArray().model("SubModel2");
model.field("number").integer().range(10,20);
});
Hop.defineModel("ValidatorTest",function(model){
model.field("minMax").integer().range(5,100);
model.field("array").string().values(["red","blue","green"]);
model.field("object").values({ R:"Red", B:"Blue", G:"Green" });
model.field("string").string().regexp(/[A-Z]+/,"REXP");
model.field("arrayOfModels").model("SubModel1").isArray();
model.field("subModel2").model("SubModel2");
model.field("arrayOfStrings").string().isArray().regexp(/[A-Z]{2,3}/,"Invalid string specified");
});
Hop.defineModel("HashModel",function(model){
model.field("subModel1Hash").model("SubModel1").isHash();
model.field("subModel2Hash").model("SubModel2",["string"]).isHash();
});
Hop.defineModel("ModelArraySizes",function(model){
model.field("subModelArray").model("SubModel1").isArray(2,4);
});
Hop.defineModel("ValidatorTest2",function(model){
model.field("subModel1").model("SubModel1",["yetAnotherArrayOfModels","number"]);
model.field("subModel2").model("SubModel2",["string"]);
});
Hop.defineClass("ValidatorTest",ValidatorTest,function(api){
api.post("test","/validator/test").demands("minMax","array","object","string","arrayOfModels","subModel2").optionals("arrayOfStrings").useModel("ValidatorTest");
api.post("test2","/validator/test2").demands("subModel1","subModel2").useModel("ValidatorTest2");
api.post("test3","/validator/test3").demands("subModelArray").useModel("ModelArraySizes");
api.post("test4","/validator/test4").demands("subModel1Hash","subModel2Hash").useModel("HashModel");
});
Hop.defineTestCase("ValidatorTest.test: Basic tests",function(test){
test.do("ValidatorTest.test").with({ minMax: 7, array: 'red', object: 'R' ,string:"A", arrayOfModels:[], subModel2:{} }).noError();
test.do("ValidatorTest.test").with({ minMax: 7, array: 'red', object: 'R' ,string:"A", arrayOfModels:"A", subModel2:{} }).errorContains("Invalid type, expected array: arrayOfModels");
test.do("ValidatorTest.test").with({ minMax: 7, array: 'red', object: 'R' ,string:"A", arrayOfModels:{}, subModel2:{} }).errorContains("Invalid type, expected array: arrayOfModels");
test.do("ValidatorTest.test").with({ minMax: 7, array: 'red', object: 'R' ,string:"A", arrayOfModels:[], subModel2:{ string: 5} }).errorContains("Invalid value, string expected: subModel2.string");
test.do("ValidatorTest.test").with({ minMax: 7, array: 'red', object: 'R' ,string:"A", arrayOfModels:[], subModel2:{ string: "AZ"} }).noError();
test.do("ValidatorTest.test").with({ minMax: 7, array: 'red', object: 'R' ,string:"A", arrayOfModels:[ { } ], subModel2:{ string: "AZ"} }).noError();
test.do("ValidatorTest.test").with({ minMax: 7, array: 'red', object: 'R' ,string:"A", arrayOfModels:[], subModel2:{}, arrayOfStrings:[ 1 ] }).errorContains("Invalid value, string expected: arrayOfStrings[0]");
test.do("ValidatorTest.test").with({ minMax: 7, array: 'red', object: 'R' ,string:"A", arrayOfModels:[], subModel2:{}, arrayOfStrings:[ "AD","DA",1 ] }).errorContains("Invalid value, string expected: arrayOfStrings[2]");
test.do("ValidatorTest.test").with({ minMax: 7, array: 'red', object: 'R' ,string:"A", arrayOfModels:[ { number:10, yetAnotherArrayOfModels:"A" } ], subModel2:{ string: "AZ"} }).errorContains("Invalid type, expected array: arrayOfModels[0].yetAnotherArrayOfModels");
test.do("ValidatorTest.test").with({ minMax: 7, array: 'red', object: 'R' ,string:"A", arrayOfModels:[ { number:10, yetAnotherArrayOfModels:[ { string:33 } ] } ], subModel2:{ string: "AZ"} }).errorContains("Invalid value, string expected: arrayOfModels[0].yetAnotherArrayOfModels[0].string");
test.do("ValidatorTest.test").with({ minMax: 7, array: 'red', object: 'R' ,string:"A", arrayOfModels:[ { number:10, yetAnotherArrayOfModels:[ { string:"AA" }, {string:33} ] } ], subModel2:{ string: "AZ"} }).errorContains("Invalid value, string expected: arrayOfModels[0].yetAnotherArrayOfModels[1].string");
test.do("ValidatorTest.test").with({ minMax: 7, array: 'red', object: 'R' ,string:"A", arrayOfModels:[ {}, { number:10, yetAnotherArrayOfModels:[ { string:"AA" }, {string:33} ] } ], subModel2:{ string: "AZ"} }).errorContains("Invalid value, string expected: arrayOfModels[1].yetAnotherArrayOfModels[1].string");
test.do("ValidatorTest.test").with({ minMax: 7, array: 'red', object: 'R' ,string:"A", arrayOfModels:[ {}, { number:10, yetAnotherArrayOfModels:[ { string:"AA" }, {string:"LL"} ] } ], subModel2:{ string: "AZ"} }).noError();
test.do("ValidatorTest.test").with({ minMax: 2, array: 'red', object: 'R',string:"A",arrayOfModels:[], subModel2:{} }).errorContains("greater than");
test.do("ValidatorTest.test").with({ minMax: 101, array: 'red', object: 'R',string:"A",arrayOfModels:[], subModel2:{} }).errorContains("less than");
test.do("ValidatorTest.test").with({ minMax: 7, array: 'sred', object: 'R',string:"A", arrayOfModels:[], subModel2:{} }).errorContains("values are");
test.do("ValidatorTest.test").with({ minMax: 7, array: 'red', object: 'X',string:"A",arrayOfModels:[], subModel2:{} }).errorContains("values are");
test.do("ValidatorTest.test").with({ minMax: 7, array: 'red', object: 'R',string:"3",arrayOfModels:[], subModel2:{} }).errorContains("REXP");
});
Hop.defineTestCase("ValidatorTest.test2",function(test){
test.do("ValidatorTest.test2").with({ subModel1:{}, subModel2:{}}).errorContains("Missing required value: subModel1.yetAnotherArrayOfModels");
test.do("ValidatorTest.test2").with({ subModel1:{ yetAnotherArrayOfModels:[] }, subModel2:{}}).errorContains("Missing required value: subModel1.number");
test.do("ValidatorTest.test2").with({ subModel1:{ yetAnotherArrayOfModels:[],number:12 }, subModel2:{ }}).errorContains("Missing required value: subModel2.string");
test.do("ValidatorTest.test2").with({ subModel1:{ yetAnotherArrayOfModels:[],number:12 }, subModel2:{ string:"AA"}}).noError();
});
Hop.defineTestCase("ValidatorTest.test3",function(test){
test.do("ValidatorTest.test3").with({ subModelArray:[] }).errorContains("Array must have at least 2 item(s): subModelArray");
test.do("ValidatorTest.test3").with({ subModelArray:[ { }, { }, { }, { }, { } ] }).errorContains("Array must have no more than 4 item(s): subModelArray");
test.do("ValidatorTest.test3").with({ subModelArray:[ { }, { } ] }).noError();
});
Hop.defineTestCase("ValidatorTest.test4",function(test){
test.do("ValidatorTest.test4").with({ subModel1Hash: { }, subModel2Hash:{} }).noError();
test.do("ValidatorTest.test4").with({ subModel1Hash: { foo:{ number: 7 }}, subModel2Hash:{} }).errorContains("Value must be greater than 10: subModel1Hash[\"foo\"].number");
test.do("ValidatorTest.test4").with({ subModel1Hash: { foo:{ number: 12 }}, subModel2Hash:{} }).noError();
test.do("ValidatorTest.test4").with({ subModel1Hash: { foo:{ number: 12 }}, subModel2Hash:{ foo: { } } }).errorContains("Missing required value: subModel2Hash[\"foo\"].string");
});
Hop.defineClass("UserService",UserService,function(api){
api.usage("Manages users");
api.post("create","/user").usage("Creates a user").demands("email","name","password").optionals("favoriteColor").useModel("User");
api.post("authenticate","/user/auth").usage("Authenticates a user").demands("password","name").useModel("User");
api.get("currentUser","/user/current").usage("Returns the current user").outputModel("User");
api.get("list","/user").usage("Lists the users");
api.get("logout","/user/logout").usage("Logs the current user out");
api.get("load","/user/:id").usage("Load a user").useModel("User");
api.del("del","/user/:id").usage("Deletes the user").demand("id").inputModel("User");
});
Hop.defineTestCase("UserService.create: Basic tests",function(test){
var validUser = { email:"test@test.com", name:"TestUser", password:"sillycat" };
test.do("UserService.create").with(validUser).inputSameAsOutput().saveOutputAs("createdUser");
test.do("UserService.del").with("createdUser").noError();
test.do("UserService.create").with(validUser, {favoriteColor:null }).errorContains("Invalid value, string expected: favoriteColor");
});
Hop.defineTestCase("UserService.create: Advanced",function(test){
var validUser = { email:"test@test.com", name:"TestUser", password:"sillycat" };
test.do("UserService.create").with(validUser).inputSameAsOutput().saveOutputAs("createdUser");
test.do("UserService.create").with(validUser,{name:undefined}).errorContains("Missing parameter");
test.do("UserService.create").with(validUser,{email:"X"}).errorContains("Invalid email");
test.do("UserService.create").with(validUser,{name:"@#$"}).errorContains("alphanumeric");
test.do("UserService.del").with("createdUser").noError();
});
Hop.defineTestCase("UserService.authenticate",function(test){
var validUser = { email:"test@test.com", name:"AuthUser", password:"sillycat" };
test.do("UserService.create").with(validUser).inputSameAsOutput().saveOutputAs("createdUser");
test.do("UserService.logout").noError();
test.do("UserService.authenticate").with({name:"authuser",password:"badpass"}).errorContains("Permission denied");
test.do("UserService.currentUser").noError().outputIsNull();
test.do("UserService.authenticate").with({name:"AuthUser",password:"sillycat"}).noError();
test.do("UserService.currentUser").outputSameAs("createdUser");
test.do("UserService.del").with("createdUser").noError();
});
Hop.apiHook("/api/",app);
app.listen(3000);