mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-02-17 08:50:58 -05:00
Wrote tests for the local mongo querier
This commit is contained in:
parent
99927d1345
commit
f2f4fef1e0
9 changed files with 188 additions and 62 deletions
|
@ -1,15 +1,18 @@
|
|||
LocalMongo = module.exports
|
||||
|
||||
#or = (list) -> _.reduce list (res, val)
|
||||
|
||||
LocalMongo.doQuerySelector = (value, operatorObj) ->
|
||||
for operator, body of operatorObj
|
||||
switch operator
|
||||
when '$gt' then return false unless value > body
|
||||
when '$gte' then return false unless value >= body
|
||||
when '$in' then return false unless value in body
|
||||
when '$in' then return false unless value in body or
|
||||
_.reduce value, ((result, val) -> result or val in body), false
|
||||
when '$lt' then return false unless value < body
|
||||
when '$lte' then return false unless value <= body
|
||||
when '$ne' then return false unless value != body
|
||||
when '$nin' then return false if value in body
|
||||
when '$nin' then return false if value of body
|
||||
true
|
||||
|
||||
|
||||
|
@ -23,7 +26,8 @@ LocalMongo.doLogicalOperator = (target, operatorObj) ->
|
|||
|
||||
LocalMongo.matchesQuery = (target, query) ->
|
||||
for key, value of query
|
||||
return false unless key in target
|
||||
return false unless key of target
|
||||
if typeof value != 'object'
|
||||
return false unless target[key] == value
|
||||
else return false unless doQuerySelector value query[key]
|
||||
return false unless target[key] == value or (target[key] in value if _.isArray value)
|
||||
else return false unless doQuerySelector value query[key]
|
||||
true
|
|
@ -1,70 +1,43 @@
|
|||
c = require './../schemas'
|
||||
|
||||
module.exports =
|
||||
AchievementSchema :
|
||||
AchievementSchema =
|
||||
type: 'object'
|
||||
properties:
|
||||
name: c.shortString({title: 'Display Name'})
|
||||
query: { $ref: 'mongoFindQuery' } # TODO make this happen
|
||||
worth:
|
||||
type: 'number'
|
||||
collection:
|
||||
type: 'string'
|
||||
worth: { type: 'number' }
|
||||
collection: { type: 'string' }
|
||||
description: { type: 'string' }
|
||||
proportionalTo:
|
||||
type: 'string'
|
||||
description: 'For repeatables only. Denotes the field a repeatable achievement needs for its calculations'
|
||||
ratio:
|
||||
type: 'integer'
|
||||
description: 'For repeatables only. Denotes how many proportionalTo\'s trigger an achievement. Usually 1.'
|
||||
minimum: 1
|
||||
required: ['name', 'query', 'worth', 'collection']
|
||||
|
||||
EarnedAchievementSchema :
|
||||
type: 'object'
|
||||
properties:
|
||||
user: c.objectId
|
||||
links:
|
||||
[
|
||||
{
|
||||
rel: 'extra'
|
||||
href: "/db/user/{($)}"
|
||||
}
|
||||
]
|
||||
achievement: c.objectId
|
||||
links:
|
||||
[
|
||||
{
|
||||
rel: 'extra'
|
||||
href: '/db/user/{($)}'
|
||||
}
|
||||
]
|
||||
achievedAmount:
|
||||
type: 'number'
|
||||
MongoFindQuerySchema =
|
||||
title: 'MongoDB Query'
|
||||
id: 'mongoFindQuery'
|
||||
type: 'object'
|
||||
patternProperties:
|
||||
'^[a-zA-Z0-9_\-\$]*$':
|
||||
type: [ 'string', 'object' ]
|
||||
oneOf: [
|
||||
{ $ref: 'mongoQueryOperator' }, # TODO make this happen
|
||||
{ type: 'string' }
|
||||
]
|
||||
additionalProperties: false
|
||||
|
||||
MongoFindQuerySchema :
|
||||
title: 'MongoDB Query'
|
||||
id: 'mongoFindQuery'
|
||||
type: 'object'
|
||||
patternProperties:
|
||||
'^[a-zA-Z0-9_\-\$]*$':
|
||||
type: [ 'string', 'object' ]
|
||||
oneOf: [
|
||||
{ $ref: 'mongoQueryOperator' }, # TODO make this happen
|
||||
{ type: 'string' }
|
||||
]
|
||||
additionalProperties: false
|
||||
|
||||
# TODO add these: http://docs.mongodb.org/manual/reference/operator/query/
|
||||
MongoQueryOperatorSchema :
|
||||
title: 'MongoDB Query operator'
|
||||
id: 'mongoQueryOperator'
|
||||
type: 'object'
|
||||
properties:
|
||||
'$gt': type: 'number'
|
||||
'$gte': type: 'number'
|
||||
'$in': type: 'array'
|
||||
'$lt': type: 'number'
|
||||
'$lte': type: 'number'
|
||||
'$ne': type: [ 'number', 'string' ]
|
||||
'$nin': type: 'array'
|
||||
additionalProperties: true # TODO set to false when the schema's done
|
||||
# TODO add these: http://docs.mongodb.org/manual/reference/operator/query/
|
||||
MongoQueryOperatorSchema =
|
||||
title: 'MongoDB Query operator'
|
||||
id: 'mongoQueryOperator'
|
||||
type: 'object'
|
||||
properties:
|
||||
'$gt': type: 'number'
|
||||
'$gte': type: 'number'
|
||||
'$in': type: 'array'
|
||||
'$lt': type: 'number'
|
||||
'$lte': type: 'number'
|
||||
'$ne': type: [ 'number', 'string' ]
|
||||
'$nin': type: 'array'
|
||||
additionalProperties: true # TODO set to false when the schema's done
|
|
@ -0,0 +1,26 @@
|
|||
c = require './../schemas'
|
||||
|
||||
module.exports =
|
||||
EarnedAchievementSchema =
|
||||
type: 'object'
|
||||
properties:
|
||||
user: c.objectId
|
||||
links:
|
||||
[
|
||||
{
|
||||
rel: 'extra'
|
||||
href: "/db/user/{($)}"
|
||||
}
|
||||
]
|
||||
achievement: c.objectId
|
||||
links:
|
||||
[
|
||||
{
|
||||
rel: 'extra'
|
||||
href: '/db/user/{($)}'
|
||||
}
|
||||
]
|
||||
achievedAmount:
|
||||
type: 'number'
|
||||
notified:
|
||||
type: 'boolean'
|
|
@ -0,0 +1,13 @@
|
|||
mongoose = require('mongoose')
|
||||
jsonschema = require('../../app/schemas/models/achievement')
|
||||
|
||||
# `pre` and `post` are not called for update operations executed directly on the database,
|
||||
# including `Model.update`,`.findByIdAndUpdate`,`.findOneAndUpdate`, `.findOneAndRemove`,and `.findByIdAndRemove`.order
|
||||
# to utilize `pre` or `post` middleware, you should `find()` the document, and call the `init`, `validate`, `save`,
|
||||
# or `remove` functions on the document. See [explanation](http://github.com/LearnBoost/mongoose/issues/964).
|
||||
|
||||
AchievementSchema = new mongoose.Schema({
|
||||
query: Object
|
||||
}, {strict: false})
|
||||
|
||||
module.exports = Achievement = mongoose.model('achievements', AchievementSchema)
|
|
@ -0,0 +1,8 @@
|
|||
mongoose = require 'mongoose'
|
||||
jsonschema = require '../../../app/schemas/models/achievement_earned'
|
||||
|
||||
AchievementEarnedSchema = new mongoose.Schema({
|
||||
user: Object
|
||||
}, {strict:false})
|
||||
|
||||
module.exports = AchievementEarned = mongoose.model('achievements.earned', AchievementEarnedSchema)
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
mongoose = require('mongoose')
|
||||
plugins = require('../../plugins/plugins')
|
||||
AchievablePlugin = require '../../plugins/achievements'
|
||||
jsonschema = require('../../../app/schemas/models/level_session')
|
||||
|
||||
LevelSessionSchema = new mongoose.Schema({
|
||||
|
@ -10,6 +11,7 @@ LevelSessionSchema = new mongoose.Schema({
|
|||
'default': Date.now
|
||||
}, {strict: false})
|
||||
LevelSessionSchema.plugin(plugins.PermissionsPlugin)
|
||||
LevelSessionSchema.plugin(AchievablePlugin)
|
||||
|
||||
LevelSessionSchema.pre 'init', (next) ->
|
||||
# TODO: refactor this into a set of common plugins for all models?
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
mongoose = require('mongoose')
|
||||
Achievement = require('../achievements/Achievement')
|
||||
AchievementEarned = require '../achievements/earned/AchievementEarned'
|
||||
|
||||
achievements = {}
|
||||
|
||||
loadAchievements = ->
|
||||
achievements = {}
|
||||
query = Achievement.find({})
|
||||
query.exec (err, docs) ->
|
||||
_.each docs, (achievement) ->
|
||||
achievements[achievement.get 'collection'] = [] unless achievement.collection in achievements
|
||||
achievements[achievement.get 'collection'].push achievement
|
||||
|
||||
loadAchievements()
|
||||
|
||||
|
||||
|
||||
# TODO make a difference between '$userID' and '$userObjectID' ?
|
||||
module.exports = AchievablePlugin = (schema, options) ->
|
||||
checkForAchievement = (doc) ->
|
||||
collectionName = doc.constructor.modelName
|
||||
console.log achievements
|
||||
for achievement in achievements[collectionName]
|
||||
console.log achievement.get 'name'
|
||||
|
||||
fetched = {}
|
||||
|
||||
schema.post 'init', (doc) ->
|
||||
fetched[doc.id] = doc
|
||||
collectionName = doc.constructor.modelName
|
||||
for achievement in achievements[collectionName]
|
||||
console.log achievement.get 'name'
|
||||
|
||||
schema.post 'save', (doc) ->
|
||||
collectionName = doc.constructor.modelName
|
||||
docBefore = fetched?.doc.id
|
||||
for achievement in achievements[collectionName]
|
||||
"placeholder"
|
||||
# continue if init'd and already achieved
|
||||
# else if new doc validates, new achievement! make the fucker
|
|
@ -4,6 +4,7 @@ crypto = require('crypto')
|
|||
{salt, isProduction} = require('../../server_config')
|
||||
mail = require '../commons/mail'
|
||||
log = require 'winston'
|
||||
plugins = require '../plugins/achievements'
|
||||
|
||||
sendwithus = require '../sendwithus'
|
||||
|
||||
|
|
58
test/app/lib/local_mongo.spec.coffee
Normal file
58
test/app/lib/local_mongo.spec.coffee
Normal file
|
@ -0,0 +1,58 @@
|
|||
describe 'Local Mongo queries', ->
|
||||
LocalMongo = require 'lib/LocalMongo'
|
||||
console.warn 'matchesQuery' in LocalMongo
|
||||
|
||||
beforeEach ->
|
||||
this.fixture1 =
|
||||
'id': 'somestring'
|
||||
'value': 9000
|
||||
'worth': 6
|
||||
'type': 'unicorn'
|
||||
'likes': ['poptarts', 'popsicles', 'popcorn']
|
||||
|
||||
it 'regular match of a property', ->
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'gender': 'unicorn')).toBeFalsy()
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'type':'unicorn')).toBeTruthy()
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'type':'zebra')).toBeFalsy()
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'type':'unicorn', 'id':'somestring')).toBeTruthy()
|
||||
|
||||
xit 'array match of a property', ->
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'likes':'poptarts')).toBeTruthy()
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'likes':'walks on the beach')).toBeFalsy()
|
||||
|
||||
xit '$gt selector', ->
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'value': '$gt': 8000)).toBeTruthy()
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'value': '$gt': [8000, 10000])).toBeTruthy()
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'value': '$gt': 9000)).toBeFalsy()
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'value': {'$gt': 8000}, 'worth': {'$gt': 5})).toBeTruthy()
|
||||
|
||||
xit '$gte selector', ->
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'value': '$gte': 9001)).toBeFalsy()
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'value': '$gte': 9000)).toBeTruthy()
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'value': '$gte': [9000, 10000])).toBeTruthy()
|
||||
|
||||
xit '$in selector', ->
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'type': '$in': ['unicorn', 'zebra'])).toBeTruthy()
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'type': '$in': ['cats', 'dogs'])).toBeFalsy()
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'likes': '$in': ['popcorn', 'chicken'])).toBeTruthy()
|
||||
|
||||
xit '$lt selector', ->
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'value': '$lt': 9001)).toBeTruthy()
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'value': '$lt': 9000)).toBeFalsy()
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'value': {'$lt': 9001}, 'worth': {'$lt': 7})).toBeTruthy()
|
||||
|
||||
xit '$lte selector', ->
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'value': '$lte': 9000)).toBeTruthy()
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'value': '$lte': 8000)).toBeFalsy()
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'value': {'$lte': 9000}, 'value': {'$lte': [6, 5]})).toBeTruthy()
|
||||
|
||||
xit '$ne selector', ->
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'value': '$ne': 9000)).toBeFalsy()
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'id': '$ne': 'otherstring')).toBeTruthy()
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'id': '$ne': ['otherstring', 'somestring'])).toBeFalsy()
|
||||
|
||||
xit '$in selector', ->
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'type': '$nin': ['unicorn', 'zebra'])).toBeFalsy()
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'type': '$nin': ['cats', 'dogs'])).toBeTruthy()
|
||||
expect(LocalMongo.matchesQuery(this.fixture1, 'likes': '$nin': ['popcorn', 'chicken'])).toBeFalsy()
|
||||
|
Loading…
Reference in a new issue