Просмотр исходного кода

Merge pull request #16 from crowi/test

Add test library and set up CircleCI
Sotaro KARASAWA 11 лет назад
Родитель
Сommit
16f46b34ec
68 измененных файлов с 198 добавлено и 59 удалено
  1. 21 3
      Gruntfile.js
  2. 2 0
      README.md
  3. 7 7
      app.js
  4. 19 0
      circle.yml
  5. 0 35
      config/default.js.dist
  6. 0 0
      lib/form/admin/app.js
  7. 0 0
      lib/form/admin/aws.js
  8. 0 0
      lib/form/admin/fb.js
  9. 0 0
      lib/form/admin/google.js
  10. 0 0
      lib/form/admin/mail.js
  11. 2 2
      lib/form/admin/sec.js
  12. 0 0
      lib/form/admin/userInvite.js
  13. 0 0
      lib/form/index.js
  14. 0 0
      lib/form/invited.js
  15. 0 0
      lib/form/login.js
  16. 0 0
      lib/form/me/password.js
  17. 0 0
      lib/form/me/user.js
  18. 0 0
      lib/form/register.js
  19. 0 0
      lib/form/revision.js
  20. 0 0
      lib/models/bookmark.js
  21. 1 1
      lib/models/config.js
  22. 0 0
      lib/models/index.js
  23. 0 0
      lib/models/page.js
  24. 0 0
      lib/models/revision.js
  25. 0 0
      lib/models/user.js
  26. 0 0
      lib/routes/admin.js
  27. 1 1
      lib/routes/index.js
  28. 0 0
      lib/routes/installer.js
  29. 3 3
      lib/routes/login.js
  30. 0 0
      lib/routes/logout.js
  31. 3 3
      lib/routes/me.js
  32. 0 0
      lib/routes/page.js
  33. 0 0
      lib/routes/user.js
  34. 0 0
      lib/util/fileUploader.js
  35. 0 0
      lib/util/formUtil.js
  36. 0 0
      lib/util/googleAuth.js
  37. 0 0
      lib/util/mailer.js
  38. 1 1
      lib/util/middlewares.js
  39. 0 0
      lib/util/swigFunctions.js
  40. 0 0
      lib/views/500.html
  41. 0 0
      lib/views/_form.html
  42. 0 0
      lib/views/admin/app.html
  43. 0 0
      lib/views/admin/index.html
  44. 0 0
      lib/views/admin/users.html
  45. 0 0
      lib/views/index.html
  46. 0 0
      lib/views/installer.html
  47. 0 0
      lib/views/invited.html
  48. 0 0
      lib/views/layout/2column.html
  49. 0 0
      lib/views/layout/layout.html
  50. 0 0
      lib/views/layout/single-nologin.html
  51. 0 0
      lib/views/layout/single.html
  52. 0 0
      lib/views/login.html
  53. 0 0
      lib/views/login/error.html
  54. 0 0
      lib/views/mail/admin/userInvitation.txt
  55. 0 0
      lib/views/mail/admin/userWaitingActivation.txt
  56. 0 0
      lib/views/me/index.html
  57. 0 0
      lib/views/me/password.html
  58. 0 0
      lib/views/modal/widget_help.html
  59. 0 0
      lib/views/modal/widget_rename.html
  60. 0 0
      lib/views/modal/widget_today_memo.html
  61. 0 0
      lib/views/page.html
  62. 0 0
      lib/views/page_list.html
  63. 0 0
      lib/views/page_presentation.html
  64. 0 0
      lib/views/user_page.html
  65. 0 0
      lib/views/widget/searcher.html
  66. 17 3
      package.json
  67. 43 0
      test/bootstrap.js
  68. 78 0
      test/models/config.test.js

+ 21 - 3
Gruntfile.js

@@ -1,11 +1,12 @@
 /*
- * @package RMW
+ * @package Crowi
  */
 
 module.exports = function(grunt) {
 
   var paths = {
-        scripts: ['Gruntfile.js', 'app.js', 'lib/**/*.js', 'models/**/*.js', 'routes/**/*.js', 'form/**/*.js', 'resource/js/**/*.js'],
+        scripts: ['Gruntfile.js', 'app.js', 'lib/**/*.js', 'resource/js/**/*.js'],
+        tests: ['test/**/*.test.js'],
         styles: ['resource/css/*.scss'],
         all: []
       };
@@ -99,6 +100,18 @@ module.exports = function(grunt) {
       },
       all: paths.scripts
     },
+    mochaTest: {
+      all: {
+        src: ['test/**/*.test.js'],
+        options: {
+          globals: ['chai'],
+          require: ['test/bootstrap.js'],
+          timeout: 3000,
+          quiet: false,
+          clearRequireCache: true,
+        },
+      }
+    },
     watch: {
       css: {
         files: paths.styles,
@@ -108,6 +121,10 @@ module.exports = function(grunt) {
         files: paths.all,
         tasks: ['dev'],
       },
+      test: {
+        files: paths.all,
+        tasks: ['test'],
+      },
       default: {
         files: paths.all,
         tasks: ['default'],
@@ -121,10 +138,11 @@ module.exports = function(grunt) {
   grunt.loadNpmTasks('grunt-contrib-concat');
   grunt.loadNpmTasks('grunt-contrib-jshint');
   grunt.loadNpmTasks('grunt-sass');
-
+  grunt.loadNpmTasks('grunt-mocha-test');
 
   // grunt watch dev
   grunt.registerTask('default', ['sass', 'concat', 'uglify']);
   grunt.registerTask('dev', ['sass:dev', 'concat', 'jshint']);
+  grunt.registerTask('test', ['mochaTest']);
 
 };

+ 2 - 0
README.md

@@ -4,6 +4,8 @@ Crowi - The Simple & Powerful Communication Tool Based on Wiki
 
 [![Deploy](https://www.herokucdn.com/deploy/button.png)](https://heroku.com/deploy)
 
+[![Circle CI](https://circleci.com/gh/crowi/crowi.svg?style=svg)](https://circleci.com/gh/crowi/crowi)
+
 
 Crowi is:
 

+ 7 - 7
app.js

@@ -13,7 +13,7 @@ var express  = require('express')
   , facebook = require('facebook-node-sdk')
   , mongo    = require('mongoose')
   , socketio = require('socket.io')
-  , middleware = require('./lib/middlewares')
+  , middleware = require('./lib/util/middlewares')
   , time     = require('time')
   , async    = require('async')
   , session  = require('express-session')
@@ -74,18 +74,18 @@ app.use(express.logger());
 app.engine('html', cons.swig);
 app.set('view cache', false);
 app.set('view engine', 'html');
-app.set('views', __dirname + '/views');
+app.set('views', __dirname + '/lib/views');
 app.use(express.methodOverride());
 app.use(express.bodyParser());
 app.use(express.cookieParser());
 app.use(session(sessionConfig));
 app.use(flash());
 
-configModel = require('./models/config')(app);
+configModel = require('./lib/models/config')(app);
 
 async.series([
   function (next) {
-    configModel.getConfigArray(function(err, doc) {
+    configModel.loadAllConfig(function(err, doc) {
       app.set('config', doc);
 
       return next();
@@ -96,9 +96,9 @@ async.series([
       ;
 
 
-    app.set('mailer', require('./lib/mailer')(app));
+    app.set('mailer', require('./lib/util/mailer')(app));
 
-    models = require('./models')(app);
+    models = require('./lib/models')(app);
     models.Config = configModel;
 
     // configure application
@@ -190,7 +190,7 @@ async.series([
     });
 
     app.set('io', io);
-    require('./routes')(app);
+    require('./lib/routes')(app);
 
     next();
   }

+ 19 - 0
circle.yml

@@ -0,0 +1,19 @@
+machine:
+  timezone: UTC
+  services:
+    - mongodb
+  environment:
+    MONGO_URI: mongodb://127.0.0.1/crowi_test
+deployment:
+  demo:
+    branch: master
+    heroku:
+      appname: crowi-demo
+  dev:
+    branch: /(master|wip-v.*)/
+    heroku:
+      appname: crowi-dev
+  strk:
+    branch: master
+    heroku:
+      appname: strk-wiki

+ 0 - 35
config/default.js.dist

@@ -1,35 +0,0 @@
-/**
- * default config
- */
-
-module.exports = {
-  app: {
-    title: 'Crocos Wiki'
-  },
-  security: {
-    confidential: '',
-    passwordSeed: "j9a5gt", // please change here
-    registrationMode: 'Restricted', // Open, Restricted, Closed
-    registrationWhiteList: []
-  },
-  aws: {
-    bucket: 'crowi',
-    region: 'ap-northeast-1',
-    accessKeyId: '',
-    secretAccessKey: ''
-  },
-  searcher: {
-    url: 'https:// ...' // crocos-wikis
-  },
-  google: {
-    clientId: '',
-    clientSecret: ''
-  },
-  facebook: {
-    appId: '',
-    secret: ''
-  },
-  session: {
-    secret: 'please input here some string',
-  }
-}

+ 0 - 0
form/admin/app.js → lib/form/admin/app.js


+ 0 - 0
form/admin/aws.js → lib/form/admin/aws.js


+ 0 - 0
form/admin/fb.js → lib/form/admin/fb.js


+ 0 - 0
form/admin/google.js → lib/form/admin/google.js


+ 0 - 0
form/admin/mail.js → lib/form/admin/mail.js


+ 2 - 2
form/admin/sec.js → lib/form/admin/sec.js

@@ -2,8 +2,8 @@
 
 var form = require('express-form')
   , field = form.field
-  , stringToArray = require('../../lib/formUtil').stringToArrayFilter
-  , normalizeCRLF = require('../../lib/formUtil').normalizeCRLFFilter
+  , stringToArray = require('../../util/formUtil').stringToArrayFilter
+  , normalizeCRLF = require('../../util/formUtil').normalizeCRLFFilter
   ;
 
 module.exports = form(

+ 0 - 0
form/admin/userInvite.js → lib/form/admin/userInvite.js


+ 0 - 0
form/index.js → lib/form/index.js


+ 0 - 0
form/invited.js → lib/form/invited.js


+ 0 - 0
form/login.js → lib/form/login.js


+ 0 - 0
form/me/password.js → lib/form/me/password.js


+ 0 - 0
form/me/user.js → lib/form/me/user.js


+ 0 - 0
form/register.js → lib/form/register.js


+ 0 - 0
form/revision.js → lib/form/revision.js


+ 0 - 0
models/bookmark.js → lib/models/bookmark.js


+ 1 - 1
models/config.js → lib/models/config.js

@@ -141,7 +141,7 @@ module.exports = function(app) {
   {
   };
 
-  configSchema.statics.getConfigArray = function(callback)
+  configSchema.statics.loadAllConfig = function(callback)
   {
     var Config = this
       , config = {};

+ 0 - 0
models/index.js → lib/models/index.js


+ 0 - 0
models/page.js → lib/models/page.js


+ 0 - 0
models/revision.js → lib/models/revision.js


+ 0 - 0
models/user.js → lib/models/user.js


+ 0 - 0
routes/admin.js → lib/routes/admin.js


+ 1 - 1
routes/index.js → lib/routes/index.js

@@ -1,5 +1,5 @@
 module.exports = function(app) {
-  var middleware = require('../lib/middlewares')
+  var middleware = require('../util/middlewares')
     , form      = require('../form')
     , page      = require('./page')(app)
     , login     = require('./login')(app)

+ 0 - 0
routes/installer.js → lib/routes/installer.js


+ 3 - 3
routes/login.js → lib/routes/login.js

@@ -81,7 +81,7 @@ module.exports = function(app) {
   };
 
   actions.loginGoogle = function(req, res) {
-    var googleAuth = require('../lib/googleAuth')(app);
+    var googleAuth = require('../util/googleAuth')(app);
     var code = req.session.googleAuthCode || null;
 
     if (!code) {
@@ -134,7 +134,7 @@ module.exports = function(app) {
 
   actions.register = function(req, res) {
     var registerForm = req.form.registerForm || {};
-    var googleAuth = require('../lib/googleAuth')(app);
+    var googleAuth = require('../util/googleAuth')(app);
 
     // ログイン済みならさようなら
     if (req.user) {
@@ -258,7 +258,7 @@ module.exports = function(app) {
   };
 
   actions.registerGoogle = function(req, res) {
-    var googleAuth = require('../lib/googleAuth')(app);
+    var googleAuth = require('../util/googleAuth')(app);
     googleAuth.createAuthUrl(req, function(err, redirectUrl) {
       if (err) {
         // TODO

+ 0 - 0
routes/logout.js → lib/routes/logout.js


+ 3 - 3
routes/me.js → lib/routes/me.js

@@ -12,7 +12,7 @@ module.exports = function(app) {
   actions.api = api;
 
   api.uploadPicture = function (req, res) {
-    var fileUploader = require('../lib/fileUploader')(app);
+    var fileUploader = require('../util/fileUploader')(app);
     var tmpFile = req.files.userPicture || null;
     if (!tmpFile) {
       return res.json({
@@ -164,7 +164,7 @@ module.exports = function(app) {
   };
 
   actions.authGoogle = function(req, res) {
-    var googleAuth = require('../lib/googleAuth')(app);
+    var googleAuth = require('../util/googleAuth')(app);
 
     var userData = req.user;
 
@@ -191,7 +191,7 @@ module.exports = function(app) {
   };
 
   actions.authGoogleCallback = function(req, res) {
-    var googleAuth = require('../lib/googleAuth')(app);
+    var googleAuth = require('../util/googleAuth')(app);
     var userData = req.user;
 
     googleAuth.handleCallback(req, function(err, tokenInfo) {

+ 0 - 0
routes/page.js → lib/routes/page.js


+ 0 - 0
routes/user.js → lib/routes/user.js


+ 0 - 0
lib/fileUploader.js → lib/util/fileUploader.js


+ 0 - 0
lib/formUtil.js → lib/util/formUtil.js


+ 0 - 0
lib/googleAuth.js → lib/util/googleAuth.js


+ 0 - 0
lib/mailer.js → lib/util/mailer.js


+ 1 - 1
lib/middlewares.js → lib/util/middlewares.js

@@ -23,7 +23,7 @@ exports.loginChecker = function(app, models) {
 
 exports.swigFunctions = function(app) {
   return function(req, res, next) {
-    res.locals(require('../lib/swigFunctions')(app));
+    res.locals(require('../util/swigFunctions')(app));
     next();
   };
 };

+ 0 - 0
lib/swigFunctions.js → lib/util/swigFunctions.js


+ 0 - 0
views/500.html → lib/views/500.html


+ 0 - 0
views/_form.html → lib/views/_form.html


+ 0 - 0
views/admin/app.html → lib/views/admin/app.html


+ 0 - 0
views/admin/index.html → lib/views/admin/index.html


+ 0 - 0
views/admin/users.html → lib/views/admin/users.html


+ 0 - 0
views/index.html → lib/views/index.html


+ 0 - 0
views/installer.html → lib/views/installer.html


+ 0 - 0
views/invited.html → lib/views/invited.html


+ 0 - 0
views/layout/2column.html → lib/views/layout/2column.html


+ 0 - 0
views/layout/layout.html → lib/views/layout/layout.html


+ 0 - 0
views/layout/single-nologin.html → lib/views/layout/single-nologin.html


+ 0 - 0
views/layout/single.html → lib/views/layout/single.html


+ 0 - 0
views/login.html → lib/views/login.html


+ 0 - 0
views/login/error.html → lib/views/login/error.html


+ 0 - 0
views/mail/admin/userInvitation.txt → lib/views/mail/admin/userInvitation.txt


+ 0 - 0
views/mail/admin/userWaitingActivation.txt → lib/views/mail/admin/userWaitingActivation.txt


+ 0 - 0
views/me/index.html → lib/views/me/index.html


+ 0 - 0
views/me/password.html → lib/views/me/password.html


+ 0 - 0
views/modal/widget_help.html → lib/views/modal/widget_help.html


+ 0 - 0
views/modal/widget_rename.html → lib/views/modal/widget_rename.html


+ 0 - 0
views/modal/widget_today_memo.html → lib/views/modal/widget_today_memo.html


+ 0 - 0
views/page.html → lib/views/page.html


+ 0 - 0
views/page_list.html → lib/views/page_list.html


+ 0 - 0
views/page_presentation.html → lib/views/page_presentation.html


+ 0 - 0
views/user_page.html → lib/views/user_page.html


+ 0 - 0
views/widget/searcher.html → lib/views/widget/searcher.html


+ 17 - 3
package.json

@@ -12,6 +12,11 @@
   "contributors": [
     "Keisuke SATO <riaf@me.com> (http://riaf.jp)"
   ],
+  "config": {
+    "blanket": {
+      "pattern": "./lib/**/*.js"
+    }
+  },
   "repository": {
     "type": "git",
     "url": "https://github.com/crowi/crowi.git"
@@ -34,13 +39,14 @@
     "express-session": "~1.9.3",
     "facebook-node-sdk": "=0.1.10",
     "googleapis": "=0.4.7",
-    "grunt": "~0.4.1",
+    "grunt": "~0.4.5",
     "grunt-cli": "~0.1.13",
     "grunt-contrib-concat": "~0.5.0",
     "grunt-contrib-jshint": "^0.10.0",
     "grunt-contrib-uglify": "~0.2.2",
     "grunt-contrib-watch": "~0.5.3",
-    "grunt-sass": "~0.14.1",
+    "grunt-mocha-test": "^0.12.7",
+    "grunt-sass": "~0.17.0",
     "mongoose": "=3.8.14",
     "mongoose-paginate": "~3.1.0",
     "nodemailer": "~1.2.2",
@@ -51,7 +57,14 @@
     "swig": "=1.3.2",
     "time": "=0.10.0"
   },
-  "devDependencies": {},
+  "devDependencies": {
+    "blanket": "^1.1.6",
+    "chai": "^1.10.0",
+    "mocha": "~2.1.0",
+    "proxyquire": "~1.3.0",
+    "sinon": "^1.12.2",
+    "sinon-chai": "^2.7.0"
+  },
   "license": [
     {
       "type": "MIT",
@@ -60,6 +73,7 @@
   ],
   "scripts": {
     "start": "node app.js",
+    "test": "./node_modules/.bin/grunt test",
     "postinstall": "./node_modules/.bin/bower cache clean && ./node_modules/.bin/bower install && ./node_modules/.bin/grunt"
   },
   "env": {

+ 43 - 0
test/bootstrap.js

@@ -0,0 +1,43 @@
+'use strict';
+
+var express = require('express')
+  , async = require('async')
+  , mongoose= require('mongoose')
+  , MODEL_DIR = __dirname + '/../lib/models'
+  , mongoUri
+  , testDBUtil
+  ;
+
+mongoUri = process.env.MONGOLAB_URI || process.env.MONGOHQ_URL || process.env.MONGO_URI || null;
+
+
+testDBUtil = {
+  generateFixture: function (conn, model, fixture, cb) {
+    var m = conn.model(model);
+    async.each(fixture, function(data, next) {
+      var newDoc = new m;
+
+      Object.keys(data).forEach(function(k) {
+        newDoc[k] = data[k];
+      });
+      newDoc.save(next);
+
+    }, function(err) {
+      cb();
+    });
+  },
+  cleanUpDb: function (conn, model, cb) {
+    if (!model) {
+      return cb(null, null);
+    }
+
+    var m = conn.model(model);
+    m.remove({}, cb);
+  },
+};
+
+global.express = express;
+global.mongoose = mongoose;
+global.mongoUri = mongoUri;
+global.MODEL_DIR = MODEL_DIR;
+global.testDBUtil = testDBUtil;

+ 78 - 0
test/models/config.test.js

@@ -0,0 +1,78 @@
+var chai = require('chai')
+  , expect = chai.expect
+  , sinon = require('sinon')
+  , sinonChai = require('sinon-chai')
+  , proxyquire = require('proxyquire')
+  ;
+chai.use(sinonChai);
+
+describe('Config model test', function () {
+  var conn
+    , app = new express()
+    , Config = proxyquire(MODEL_DIR + '/config.js', {mongoose: mongoose})(app)
+    ;
+
+  before(function (done) {
+    if (mongoUri) {
+      // 基本的に mongoUri がセットされてたら、そのURIにはつながる前提
+      conn = mongoose.createConnection(mongoUri, function(err) {
+        if (err) {
+          done(); // ここで skip したいなあ
+        }
+
+        Config = conn.model('Config');
+        var fixture = [
+          {ns: 'crowi', key: 'test:test', value: JSON.stringify('crowi test value')},
+          {ns: 'crowi', key: 'test:test2', value: JSON.stringify(11111)},
+          {ns: 'crowi', key: 'test:test3', value: JSON.stringify([1, 2, 3, 4, 5])},
+          {ns: 'plugin', key: 'other:config', value: JSON.stringify('this is data')},
+        ];
+
+        testDBUtil.generateFixture(conn, 'Config', fixture, done);
+      });
+    }
+  });
+
+  beforeEach(function () {
+  });
+
+  after(function (done) {
+    if (mongoUri) {
+      testDBUtil.cleanUpDb(conn, 'Config', function(err, doc) {
+        conn.close();
+        done();
+      });
+    }
+  });
+
+  describe('.CONSTANTS', function () {
+    it('Config has constants', function() {
+      expect(Config.SECURITY_REGISTRATION_MODE_OPEN).to.have.string('Open');
+      expect(Config.SECURITY_REGISTRATION_MODE_RESTRICTED).to.have.string('Resricted');
+      expect(Config.SECURITY_REGISTRATION_MODE_CLOSED).to.have.string('Closed');
+    });
+  });
+
+  describe('.loadAllConfig', function () {
+    it('Get config array', function(done) {
+      Config.loadAllConfig(function(err, config) {
+
+        expect(config.crowi).to.be.an('Object');
+        expect(config.crowi).to.have.property('test:test')
+          .and.equal('crowi test value');
+        expect(config.crowi).to.have.property('test:test2')
+          .and.equal(11111);
+        expect(config.crowi).to.have.property('test:test3')
+          .and.to.be.instanceof(Array)
+          .and.deep.equal([1, 2, 3, 4, 5]);
+
+        expect(config.plugin).to.be.an('Object')
+          .and.have.property('other:config')
+          .and.equal('this is data');
+
+        done();
+      });
+    });
+  });
+});
+