mirror of
https://github.com/HackPlan/RootPanel.git
synced 2026-03-26 22:16:28 +08:00
add some test for account model
This commit is contained in:
@@ -1,55 +1,42 @@
|
||||
jsonStableStringify = require 'json-stable-stringify'
|
||||
getParameterNames = require 'get-parameter-names'
|
||||
redis = require 'redis'
|
||||
_ = require 'underscore'
|
||||
{EventEmitter} = require 'events'
|
||||
Redis = require 'ioredis'
|
||||
_ = require 'lodash'
|
||||
Q = require 'q'
|
||||
|
||||
###
|
||||
Public: Cache factory,
|
||||
You can access a global instance via `root.cache`.
|
||||
###
|
||||
module.exports = class CacheFactory
|
||||
module.exports = class CacheFactory extends EventEmitter
|
||||
constructor: ({host, port, password}) ->
|
||||
@redis = redis.createClient port, host,
|
||||
auth_pass: password
|
||||
@redis = new Redis {host, port, password}
|
||||
|
||||
_.extend @,
|
||||
get: Q.denodeify @redis.get.bind @redis
|
||||
del: Q.denodeify @redis.del.bind @redis
|
||||
set: Q.denodeify @redis.set.bind @redis
|
||||
setEx: Q.denodeify @redis.setex.bind @redis
|
||||
|
||||
hashKey: (key) ->
|
||||
if _.isString key
|
||||
return key
|
||||
else
|
||||
return jsonStableStringify key
|
||||
|
||||
getJSON: (key) ->
|
||||
@get(@hashKey key).then (result) ->
|
||||
getJSON: (keys) ->
|
||||
@redis.get(keys.join ':').then (result) ->
|
||||
try
|
||||
return JSON.parse result
|
||||
catch
|
||||
return null
|
||||
|
||||
try: (key, setter) ->
|
||||
@tryHelper key, setter, =>
|
||||
@set arguments...
|
||||
try: (keys, {setex}, setter) ->
|
||||
hashed = keys.join ':'
|
||||
|
||||
tryExpire: (key, expired, setter) ->
|
||||
@tryHelper key, setter, (key, value) =>
|
||||
@setEx key, expired, value
|
||||
@redis.get(hashed).then (value) =>
|
||||
if value != undefined and value != null
|
||||
try
|
||||
return JSON.parse value
|
||||
catch err
|
||||
return result
|
||||
|
||||
refresh: (key) ->
|
||||
@del @hashKey key
|
||||
else
|
||||
Q(setter keys).tap (value) =>
|
||||
if _.isObject value
|
||||
value = JSON.stringify value
|
||||
|
||||
tryHelper: (key, setter, operator) ->
|
||||
hashed_key = @hashKey key
|
||||
if setex
|
||||
@redis.setex hashed, setex, value
|
||||
else
|
||||
@redis.set hashed, value
|
||||
|
||||
@get(hashed_key).then (value) ->
|
||||
Q().then ->
|
||||
if value in [undefined, null]
|
||||
Q(setter()).then (value) ->
|
||||
command(hashed_key, value).thenReject value
|
||||
else
|
||||
return value
|
||||
clean: (keys) ->
|
||||
client.del keys.join ':'
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
expressBunyanLogger = require 'express-bunyan-logger'
|
||||
expressSession = require 'express-session'
|
||||
redisStore = require 'connect-redis'
|
||||
moment = require 'moment-timezone'
|
||||
|
||||
@@ -121,6 +121,7 @@ Account.ensureIndex
|
||||
Account.ensureIndex
|
||||
'tokens.code': 1
|
||||
,
|
||||
sparse: true
|
||||
unique: true
|
||||
|
||||
###
|
||||
@@ -167,13 +168,13 @@ Account.search = (identify) ->
|
||||
Return {Promise} resolve with `{account: Account, token: Token}` or `{}`.
|
||||
###
|
||||
Account.authenticate = (tokenCode) ->
|
||||
@findOneAndUpdate(
|
||||
@findOneAndUpdate
|
||||
'tokens.code': tokenCode
|
||||
,
|
||||
$set:
|
||||
'tokens.$.updated_at': new Date()
|
||||
|
||||
).then (account) ->
|
||||
.then (account) ->
|
||||
return {
|
||||
account: account
|
||||
|
||||
@@ -251,7 +252,7 @@ Account.register = ({username, email, password}) ->
|
||||
Public: Create token for this account.
|
||||
|
||||
* `type` {String} Type of {Token}
|
||||
* `options` {Object} Options of {Token}
|
||||
* `options` (optional) {Object} Options of {Token}
|
||||
|
||||
Return {Promise} resolve with create {Token}.
|
||||
###
|
||||
@@ -263,11 +264,10 @@ Account::createToken = (type, options) ->
|
||||
created_at: new Date()
|
||||
updated_at: new Date()
|
||||
|
||||
@update(
|
||||
@update
|
||||
$push:
|
||||
tokens: token
|
||||
).then ->
|
||||
return token
|
||||
.thenResolve token
|
||||
|
||||
###
|
||||
Public: Remove all token and create a new one just for reset password.
|
||||
|
||||
44
core/test/model/account.test.coffee
Normal file
44
core/test/model/account.test.coffee
Normal file
@@ -0,0 +1,44 @@
|
||||
describe 'model.account', ->
|
||||
Account = null
|
||||
|
||||
before ->
|
||||
{Account} = root
|
||||
|
||||
describe '.register', ->
|
||||
it 'should success', ->
|
||||
{username, email, password} = randomAccount()
|
||||
|
||||
Account.register({username, email, password}).then (account) ->
|
||||
account.username.should.be.equal username
|
||||
|
||||
describe '.search', ->
|
||||
{id, email, username} = {}
|
||||
|
||||
before ->
|
||||
createAccount().then (account) ->
|
||||
{_id: id, email, username} = account
|
||||
|
||||
it 'search by id', ->
|
||||
Account.search(id.toString()).then (account) ->
|
||||
account.username.should.be.equal username
|
||||
|
||||
it 'search by email', ->
|
||||
Account.search(email).then (account) ->
|
||||
account.username.should.be.equal username
|
||||
|
||||
it 'search by username', ->
|
||||
Account.search(username).then (account) ->
|
||||
account._id.toString().should.be.equal id.toString()
|
||||
|
||||
it 'search undefined account', ->
|
||||
Account.search(randomAccount().username).then (account) ->
|
||||
expect(account).to.not.exists
|
||||
|
||||
describe '#createToken', ->
|
||||
it 'should success', ->
|
||||
createAccount().then (account) ->
|
||||
account.createToken('full_access').then ({code}) ->
|
||||
Account.findOne('tokens.code': code).then (account) ->
|
||||
_.findWhere(account.tokens,
|
||||
code: code
|
||||
).type.should.be.equal 'full_access'
|
||||
@@ -14,16 +14,10 @@ validator.extend 'isPassword', (password) ->
|
||||
return /^.+$/.test password
|
||||
|
||||
exports.sha256 = (data) ->
|
||||
if data
|
||||
return crypto.createHash('sha256').update(data).digest('hex')
|
||||
else
|
||||
return null
|
||||
return crypto.createHash('sha256').update(data ? '').digest 'hex'
|
||||
|
||||
exports.md5 = (data) ->
|
||||
if data
|
||||
return crypto.createHash('md5').update(data).digest('hex')
|
||||
else
|
||||
return null
|
||||
return crypto.createHash('md5').update(data ? '').digest 'hex'
|
||||
|
||||
exports.randomSalt = ->
|
||||
return exports.sha256 crypto.randomBytes 256
|
||||
@@ -38,17 +32,3 @@ exports.randomString = (length) ->
|
||||
|
||||
exports.hashPassword = (password, password_salt) ->
|
||||
return exports.sha256 password_salt + exports.sha256(password)
|
||||
|
||||
exports.pickErrorName = (error) ->
|
||||
unless error and error.errors
|
||||
return null
|
||||
|
||||
if _.isEmpty error.errors
|
||||
return null
|
||||
|
||||
err = error.errors[_.first(_.keys(error.errors))]
|
||||
|
||||
if err.message == 'unique_validation_error'
|
||||
return "#{err.path}_exist"
|
||||
|
||||
return err.message
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
"express": "^4.10.4",
|
||||
"express-bunyan-logger": "^1.1.0",
|
||||
"express-session": "^1.9.2",
|
||||
"get-parameter-names": "^0.2.0",
|
||||
"insight": "^0.5.3",
|
||||
"jade": "^1.9.2",
|
||||
"json-stable-stringify": "^1.0.0",
|
||||
@@ -59,7 +58,8 @@
|
||||
"semver": "^4.1.0",
|
||||
"ssh2": "^0.3.6",
|
||||
"underscore": "^1.7.0",
|
||||
"validator": "^3.37.0"
|
||||
"validator": "^3.37.0",
|
||||
"ioredis": "^1.3.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "^1.10.0",
|
||||
|
||||
78
test/agent.coffee
Normal file
78
test/agent.coffee
Normal file
@@ -0,0 +1,78 @@
|
||||
request = require 'request'
|
||||
chai = require 'chai'
|
||||
_ = require 'lodash'
|
||||
Q = require 'q'
|
||||
|
||||
expect = chai.expect
|
||||
|
||||
methods = ['get', 'post', 'delete', 'put', 'patch', 'head', 'options']
|
||||
|
||||
module.exports = createAgent = (agent_options) ->
|
||||
if _.isNumber config.web.listen
|
||||
prefix = "http://127.0.0.1:#{config.web.listen}"
|
||||
else
|
||||
prefix = "http://unix:#{config.web.listen}:"
|
||||
|
||||
agent = {}
|
||||
|
||||
methods.forEach (method) ->
|
||||
agent[method] = (url, options, asserts) ->
|
||||
options = _.merge
|
||||
url: url
|
||||
json: true
|
||||
method: method
|
||||
followRedirect: false
|
||||
, options, agent_options
|
||||
|
||||
if options.baseUrl
|
||||
options.baseUrl = prefix + options.baseUrl
|
||||
else
|
||||
options.baseUrl = prefix + '/'
|
||||
|
||||
Q.nfcall(request, options).then ([res]) ->
|
||||
return res
|
||||
.tap (res) ->
|
||||
{status, headers, body, error} = asserts ? {}
|
||||
|
||||
message = printHttpResponse res
|
||||
|
||||
if status
|
||||
expect(res.statusCode).to.equal status, message
|
||||
else if !error
|
||||
expect(res.statusCode).to.within 200, 300, message
|
||||
|
||||
if error
|
||||
expect(res.body.error).to.equal error, message
|
||||
|
||||
assertObjectFields = (data, asserts) ->
|
||||
for field, pattern of asserts ? {}
|
||||
if pattern instanceof RegExp
|
||||
expect(data[field]).to.match pattern, message
|
||||
else
|
||||
expect(data[field]).to.equal pattern, message
|
||||
|
||||
assertObjectFields res.headers, headers
|
||||
assertObjectFields res.body, body
|
||||
|
||||
return agent
|
||||
|
||||
module.exports.methods = methods
|
||||
|
||||
printHttpResponse = ({httpVersion, statusCode, statusMessage, headers, body}) ->
|
||||
message = """
|
||||
Response:
|
||||
HTTP/#{httpVersion} #{statusCode} #{statusMessage}\n
|
||||
"""
|
||||
|
||||
for name, value of headers
|
||||
message += "#{name}: #{value}\n"
|
||||
|
||||
if headers['content-type']?.match /text\/html/
|
||||
body = body.replace / /g, ' '
|
||||
body = body.replace /<br>/g, '\n'
|
||||
else if headers['content-type']?.match /application\/json/
|
||||
body = JSON.stringify body, null, ' '
|
||||
|
||||
message += "\n#{body}"
|
||||
|
||||
return message
|
||||
@@ -1,10 +1,16 @@
|
||||
process.env.NODE_ENV = 'test'
|
||||
|
||||
_ = require 'lodash'
|
||||
|
||||
Root = require '../core'
|
||||
snippet = require './snippet'
|
||||
|
||||
global.config = require '../sample/core.config.coffee'
|
||||
global.root = new Root config
|
||||
|
||||
root.start()
|
||||
|
||||
require './snippet'
|
||||
_.extend global, snippet
|
||||
|
||||
chai.should()
|
||||
chai.config.includeStack = true
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
request = require 'request'
|
||||
chai = require 'chai'
|
||||
url = require 'url'
|
||||
_ = require 'lodash'
|
||||
Q = require 'q'
|
||||
|
||||
utils = require '../core/utils'
|
||||
createAgent = require './agent'
|
||||
|
||||
expect = chai.expect
|
||||
|
||||
chai.should()
|
||||
chai.config.includeStack = true
|
||||
|
||||
methods = ['get', 'post', 'delete', 'put', 'patch', 'head', 'options']
|
||||
|
||||
ifEnabled = (name) ->
|
||||
if name in _.keys config.plugins
|
||||
return describe
|
||||
@@ -35,60 +30,14 @@ randomAccount = ->
|
||||
email: 'test' + randomLowerCase(6) + '@gmail.com'
|
||||
}
|
||||
|
||||
createAgent = (agent_options) ->
|
||||
if _.isNumber config.web.listen
|
||||
prefix = "http://127.0.0.1:#{config.web.listen}"
|
||||
else
|
||||
prefix = "http://unix:#{config.web.listen}:"
|
||||
|
||||
agent = {}
|
||||
|
||||
methods.map (method) ->
|
||||
agent[method] = (url, options, asserts) ->
|
||||
options = _.merge
|
||||
url: url
|
||||
json: true
|
||||
method: method
|
||||
followRedirect: false
|
||||
, options, agent_options
|
||||
|
||||
if options.baseUrl
|
||||
options.baseUrl = prefix + options.baseUrl
|
||||
else
|
||||
options.baseUrl = prefix + '/'
|
||||
|
||||
Q.nfcall(request, options).then ([res]) ->
|
||||
return res
|
||||
.tap (res) ->
|
||||
{status, headers, body, error} = asserts ? {}
|
||||
|
||||
message = printHttpResponse res
|
||||
|
||||
if status
|
||||
expect(res.statusCode).to.equal status, message
|
||||
else if !error
|
||||
expect(res.statusCode).to.within 200, 300, message
|
||||
|
||||
if error
|
||||
expect(res.body.error).to.equal error, message
|
||||
|
||||
assertObjectFields = (data, asserts) ->
|
||||
for field, pattern of asserts ? {}
|
||||
if pattern instanceof RegExp
|
||||
expect(data[field]).to.match pattern, message
|
||||
else
|
||||
expect(data[field]).to.equal pattern, message
|
||||
|
||||
assertObjectFields res.headers, headers
|
||||
assertObjectFields res.body, body
|
||||
|
||||
return agent
|
||||
createAccount = ->
|
||||
root.Account.register randomAccount()
|
||||
|
||||
createLoggedAgent = (options) ->
|
||||
ready = null
|
||||
agent = {}
|
||||
|
||||
methods.map (method) ->
|
||||
createAgent.methods.map (method) ->
|
||||
agent[method] = (args...) ->
|
||||
ready ?= createAgent().post '/account/register',
|
||||
json: randomAccount()
|
||||
@@ -101,32 +50,17 @@ createLoggedAgent = (options) ->
|
||||
|
||||
return agent
|
||||
|
||||
_.extend global, {
|
||||
module.exports = {
|
||||
_
|
||||
chai
|
||||
utils
|
||||
expect
|
||||
|
||||
ifEnabled
|
||||
unlessTravis
|
||||
randomAccount
|
||||
|
||||
createAccount
|
||||
createAgent
|
||||
createLoggedAgent
|
||||
}
|
||||
|
||||
printHttpResponse = ({httpVersion, statusCode, statusMessage, headers, body}) ->
|
||||
message = """
|
||||
Response:
|
||||
HTTP/#{httpVersion} #{statusCode} #{statusMessage}\n
|
||||
"""
|
||||
|
||||
for name, value of headers
|
||||
message += "#{name}: #{value}\n"
|
||||
|
||||
if headers['content-type']?.match /text\/html/
|
||||
body = body.replace / /g, ' '
|
||||
body = body.replace /<br>/g, '\n'
|
||||
else if headers['content-type']?.match /application\/json/
|
||||
body = JSON.stringify body, null, ' '
|
||||
|
||||
message += "\n#{body}"
|
||||
|
||||
return message
|
||||
|
||||
Reference in New Issue
Block a user