Permalink
Browse files

version 0.1.0

  • Loading branch information...
petejkim committed Dec 28, 2011
1 parent 4801f86 commit 0aca51343801edb2f1265753136922a635e762ea
Showing with 446 additions and 0 deletions.
  1. +44 −0 .gitignore
  2. +20 −0 LICENSE
  3. +5 −0 Makefile
  4. +104 −0 README.md
  5. +2 −0 index.js
  6. +129 −0 lib/factory-lady.js
  7. +26 −0 package.json
  8. +116 −0 test/factory-test.js
View
@@ -0,0 +1,44 @@
+# App
+tmp/
+node_modules/
+*.swp
+**.orig
+*.pid
+*.log
+
+# OSX
+.DS_Store
+._*
+.Spotlight-V100
+.Trashes
+
+# Linux
+*~
+.directory
+
+# Windows
+Thumbs.db
+Desktop.ini
+
+# RubyMine
+.idea/
+
+# TextMate
+*.tmproj
+*.tmproject
+tmtags
+
+# Vim
+.*.sw[a-z]
+*.un~
+Session.vim
+
+# Emacs
+\#*\#
+/.emacs.desktop
+/.emacs.desktop.lock
+.elc
+auto-save-list
+tramp
+.\#*
+
View
20 LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2011 Peter Jihoon Kim
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
View
@@ -0,0 +1,5 @@
+test:
+ @./node_modules/.bin/mocha --reporter dot --ui bdd
+
+.PHONY: test
+
View
104 README.md
@@ -0,0 +1,104 @@
+# factory-lady.js
+
+Factory-lady is a factory library for [Node.js](http://nodejs.org/) / JavaScript inspired by [Factory\_girl](http://github.com/thoughtbot/factory_girl). It works asynchronously and supports lazy attributes as well as associations.
+
+It works as long as `new` keyword is used on the model to instantiate new objects and `save` method is used to persist objects. For example, [Mongoose](http://github.com/LearnBoost/mongoose.git) models follow such convention.
+
+## Installation
+
+Node.js:
+
+```
+npm install factory-lady
+```
+
+To use Factory-lady in the browser or other JavaScript environments, just copy and include `factory-lady.js` under `lib` directory.
+
+## Defining Factories
+
+JavaScript:
+
+```javascript
+var Factory = require('factory-lady')
+ , User = require('../../app/models/user')
+ , Post = require('../../app/models/post');
+
+var emailCounter = 1;
+
+Factory.define('user', User, {
+ email : function(cb) { cb('user' + emailCounter++ + '@example.com'); } // lazy attribute
+, state : 'activated'
+, password : '123456'
+});
+
+Factory.define('post', Post, {
+ user_id : Factory.assoc('user', 'id') // simply Factory.assoc('user') for user object itself
+, subject : 'Hello World'
+, content : 'Lorem ipsum dolor sit amet...'
+});
+```
+
+CoffeeScript:
+
+```coffeescript
+Factory = require 'factory-lady'
+User = require '../../app/models/user'
+Post = require '../../app/models/post'
+
+emailCounter = 1
+
+Factory.define 'user', User,
+ email : (cb) -> cb("user#{emailCounter++}@example.com") # lazy attribute
+ state : 'activated'
+ password : '123456'
+
+Factory.define 'post', Post,
+ user_id : Factory.assoc 'user', 'id' # simply Factory.assoc 'user' for user object itself
+ title : 'Hello World'
+ content : 'Lorem ipsum dolor sit amet...'
+```
+
+## Using Factories
+
+JavaScript:
+
+```javascript
+Factory.build('post', function(post) {
+ // post is a Post instance that is not saved
+});
+
+Factory.build('post', { title: 'Foo', content: 'Bar' }, function(post) {
+ // build a post and override title and content
+});
+
+Factory.create('post', function(post) {
+ // post is a saved Post instance
+});
+
+Factory('post', function(post) {
+ // post is a saved Post instance
+ // same as Factory.create
+});
+```
+
+CoffeeScript:
+
+```coffeescript
+Factory.build 'post', (post) ->
+ # post is a Post instance that is not saved
+
+Factory.build 'post', title: 'Foo', content: 'Bar', (post) ->
+ # post is a Post instance that is not saved
+
+Factory.create 'post', (post) ->
+ # post is a saved Post instance
+
+Factory 'post', (post) ->
+ # post is a saved Post instance
+ # same as Factory.create
+```
+
+## License
+
+Copyright (c) 2011 Peter Jihoon Kim. This software is licensed under the [MIT License](http://github.com/petejkim/factory-lady/raw/master/LICENSE).
+
View
@@ -0,0 +1,2 @@
+module.exports = require('./lib/factory-lady');
+
View
@@ -0,0 +1,129 @@
+(function() {
+ var hash = {
+ merge: function(obj1, obj2) {
+ if(obj1 && obj2) {
+ var key;
+ for(key in obj2) {
+ if(obj2.hasOwnProperty(key)) {
+ obj1[key] = obj2[key];
+ }
+ }
+ }
+ return obj1;
+ }
+ , copy: function(obj) {
+ var newObj = {};
+ if(obj) {
+ hash.merge(newObj, obj);
+ }
+ return newObj;
+ }
+ , keys: function(obj) {
+ var keys = [], key;
+ for(key in obj) {
+ if(obj.hasOwnProperty(key)) {
+ keys.push(key);
+ }
+ }
+ return keys;
+ }
+ };
+
+ var asyncForEach = function(array, handler, callback) {
+ var length = array.length, index = -1;
+
+ var processNext = function() {
+ index ++;
+ if(index < length) {
+ var item = array[index];
+ handler(item, processNext);
+ } else {
+ callback();
+ }
+ };
+
+ processNext();
+ };
+
+ var factories = {};
+
+ var define = function(name, model, attributes) {
+ factories[name] = {
+ model: model
+ , attributes: attributes
+ };
+ };
+
+ var build = function(name, userAttrs, callback) {
+ if(typeof userAttrs === 'function') {
+ callback = userAttrs;
+ userAttrs = {};
+ }
+
+ var model = factories[name].model;
+ var attrs = hash.copy(factories[name].attributes);
+ hash.merge(attrs, userAttrs);
+
+ asyncForEach(hash.keys(attrs), function(key, cb) {
+ var fn = attrs[key];
+ if(typeof fn === 'function') {
+ fn(function(value) {
+ attrs[key] = value;
+ cb();
+ });
+ } else {
+ cb();
+ }
+ }, function() {
+ var doc = new model();
+ var key;
+ for(key in attrs) {
+ if(attrs.hasOwnProperty(key)) {
+ doc[key] = attrs[key];
+ }
+ }
+ callback(doc);
+ });
+ };
+
+ var create = function(name, userAttrs, callback) {
+ if(typeof userAttrs === 'function') {
+ callback = userAttrs;
+ userAttrs = {};
+ }
+
+ build(name, userAttrs, function(doc) {
+ doc.save(function(err) {
+ if(err) {
+ throw err;
+ }
+ callback(doc);
+ });
+ });
+ };
+
+ var assoc = function(name, attr) {
+ return function(callback) {
+ create(name, function(doc) {
+ if(attr) {
+ callback(doc[attr]);
+ } else {
+ callback(doc);
+ }
+ });
+ };
+ };
+
+ var Factory = create;
+ Factory.define = define;
+ Factory.build = build;
+ Factory.create = create;
+ Factory.assoc = assoc;
+
+ if(typeof module !== 'undefined' && module.exports) {
+ module.exports = Factory;
+ } else {
+ this.Factory = Factory;
+ }
+}());
+
View
@@ -0,0 +1,26 @@
+{
+ "name": "factory-lady"
+, "description": "a factory library for javascript / node.js inspired by factory_girl"
+, "main": "./index"
+, "author": "Peter Jihoon Kim"
+, "version": "0.1.0"
+, "keywords": ["factory", "test", "bdd", "tdd", "fixture"]
+, "repository" : {
+ "type" : "git"
+ , "url" : "http://github.com/petejkim/factory-lady.git"
+ }
+, "bugs" : {
+ "url" : "http://github.com/petejkim/factory-lady/issues"
+ }
+, "licenses" : [
+ { "type" : "MIT"
+ , "url" : "http://github.com/petejkim/factory-lady/raw/master/LICENSE"
+ }
+ ]
+, "dependencies": {}
+, "devDependencies": {
+ "mocha" : ">= 0.7.1"
+ , "should" : ">= 0.4.2"
+ }
+}
+
Oops, something went wrong.

0 comments on commit 0aca513

Please sign in to comment.