mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-03-26 12:50:31 -04:00
parent
4827dc57e7
commit
b125f9b2fa
9 changed files with 313 additions and 293 deletions
server
spec/server
|
@ -6,7 +6,6 @@ module.exports.handlers =
|
|||
# TODO: Disabling this until we know why our app servers CPU grows out of control.
|
||||
# 'analytics_users_active': 'handlers/analytics_users_active_handler'
|
||||
'article': 'handlers/article_handler'
|
||||
'campaign': 'handlers/campaign_handler'
|
||||
'clan': 'handlers/clan_handler'
|
||||
'classroom': 'handlers/classroom_handler'
|
||||
'course': 'handlers/course_handler'
|
||||
|
|
|
@ -1,115 +0,0 @@
|
|||
Campaign = require './../models/Campaign'
|
||||
Level = require '../models/Level'
|
||||
Achievement = require '../models/Achievement'
|
||||
Handler = require '../commons/Handler'
|
||||
async = require 'async'
|
||||
mongoose = require 'mongoose'
|
||||
|
||||
CampaignHandler = class CampaignHandler extends Handler
|
||||
modelClass: Campaign
|
||||
jsonSchema: require '../../app/schemas/models/campaign.schema'
|
||||
|
||||
hasAccess: (req) ->
|
||||
req.method in ['GET'] or req.user?.isAdmin()
|
||||
|
||||
hasAccessToDocument: (req, document, method=null) ->
|
||||
return true if req.user?.isAdmin()
|
||||
|
||||
if @modelClass.schema.uses_coco_translation_coverage and (method or req.method).toLowerCase() in ['post', 'put']
|
||||
return true if @isJustFillingTranslations(req, document)
|
||||
|
||||
if req.method is 'GET'
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
get: (req, res) ->
|
||||
return @sendForbiddenError(res) if not @hasAccess(req)
|
||||
# We don't have normal text search or anything set up to make /db/campaign work, so we'll just give them all campaigns, no problem.
|
||||
query = {}
|
||||
projection = {}
|
||||
if @modelClass.schema.uses_coco_translation_coverage and req.query.view is 'i18n-coverage'
|
||||
query = i18nCoverage: {$exists: true}
|
||||
if req.query.project
|
||||
projection[field] = 1 for field in req.query.project.split(',')
|
||||
if req.query.type
|
||||
query.type = req.query.type
|
||||
q = @modelClass.find query, projection
|
||||
q.exec (err, documents) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
documents = (@formatEntity(req, doc) for doc in documents)
|
||||
@sendSuccess(res, documents)
|
||||
|
||||
getOverworld: (req, res) ->
|
||||
return @sendForbiddenError(res) if not @hasAccess(req)
|
||||
projection = {}
|
||||
if req.query.project
|
||||
projection[field] = 1 for field in req.query.project.split(',')
|
||||
q = @modelClass.find {type: 'hero'}, projection
|
||||
q.exec (err, documents) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
formatCampaign = (doc) =>
|
||||
obj = @formatEntity(req, doc)
|
||||
obj.adjacentCampaigns = _.mapValues(obj.adjacentCampaigns, (a) -> _.pick(a, ['showIfUnlocked', 'color', 'name', 'description' ]))
|
||||
for original, level of obj.levels
|
||||
obj.levels[original] = _.pick level, ['locked', 'disabled', 'original', 'rewards', 'slug']
|
||||
obj
|
||||
documents = (formatCampaign(doc) for doc in documents)
|
||||
@sendSuccess(res, documents)
|
||||
|
||||
getByRelationship: (req, res, args...) ->
|
||||
relationship = args[1]
|
||||
return @getOverworld(req,res) if args[0] is '-' and relationship is 'overworld'
|
||||
|
||||
if relationship in ['levels', 'achievements']
|
||||
projection = {}
|
||||
if req.query.project
|
||||
projection[field] = 1 for field in req.query.project.split(',')
|
||||
@getDocumentForIdOrSlug args[0], (err, campaign) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
return @sendNotFoundError(res) unless campaign?
|
||||
return @getRelatedLevels(req, res, campaign, projection) if relationship is 'levels'
|
||||
return @getRelatedAchievements(req, res, campaign, projection) if relationship is 'achievements'
|
||||
else
|
||||
super(arguments...)
|
||||
|
||||
getRelatedLevels: (req, res, campaign, projection) ->
|
||||
extraProjectionProps = []
|
||||
unless _.isEmpty(projection)
|
||||
# Make sure that permissions and version are fetched, but not sent back if they didn't ask for them.
|
||||
extraProjectionProps.push 'permissions' unless projection.permissions
|
||||
extraProjectionProps.push 'version' unless projection.version
|
||||
projection.permissions = 1
|
||||
projection.version = 1
|
||||
|
||||
levels = campaign.get('levels') or []
|
||||
|
||||
f = (levelOriginal) ->
|
||||
(callback) ->
|
||||
query = { original: mongoose.Types.ObjectId(levelOriginal) }
|
||||
sort = { 'version.major': -1, 'version.minor': -1 }
|
||||
Level.findOne(query, projection).sort(sort).exec callback
|
||||
|
||||
fetches = (f(level.original) for level in _.values(levels))
|
||||
async.parallel fetches, (err, levels) =>
|
||||
return @sendDatabaseError(res, err) if err
|
||||
filteredLevels = (_.omit(level.toObject(), extraProjectionProps) for level in levels)
|
||||
return @sendSuccess(res, filteredLevels)
|
||||
|
||||
getRelatedAchievements: (req, res, campaign, projection) ->
|
||||
levels = campaign.get('levels') or []
|
||||
|
||||
f = (levelOriginal) ->
|
||||
(callback) ->
|
||||
query = { related: levelOriginal }
|
||||
Achievement.find(query, projection).exec callback
|
||||
|
||||
fetches = (f(level.original) for level in _.values(levels))
|
||||
async.parallel fetches, (err, achievementses) =>
|
||||
achievements = _.flatten(achievementses)
|
||||
return @sendDatabaseError(res, err) if err
|
||||
return @sendSuccess(res, (achievement.toObject() for achievement in achievements))
|
||||
|
||||
getNamesByIDs: (req, res) -> @getNamesByOriginals req, res, true
|
||||
|
||||
module.exports = new CampaignHandler()
|
|
@ -7,6 +7,8 @@ mongoose = require 'mongoose'
|
|||
Campaign = require '../models/Campaign'
|
||||
parse = require '../commons/parse'
|
||||
LevelSession = require '../models/LevelSession'
|
||||
Achievement = require '../models/Achievement'
|
||||
Level = require '../models/Level'
|
||||
slack = require '../slack'
|
||||
|
||||
module.exports =
|
||||
|
@ -39,3 +41,42 @@ module.exports =
|
|||
res.status(200).send(campaign.toObject())
|
||||
docLink = "http://codecombat.com#{req.headers['x-current-path']}"
|
||||
slack.sendChangedSlackMessage creator: req.user, target: campaign, docLink: docLink
|
||||
|
||||
fetchRelatedAchievements: wrap (req, res) ->
|
||||
campaign = yield database.getDocFromHandle(req, Campaign)
|
||||
if not campaign
|
||||
throw new errors.NotFound('Campaign not found.')
|
||||
levels = campaign.get('levels') or []
|
||||
project = parse.getProjectFromReq(req)
|
||||
fetches = []
|
||||
for level in _.values(levels)
|
||||
fetches.push Achievement.find({ related: level.original }).select(project)
|
||||
achievementses = yield fetches
|
||||
achievements = _.flatten(achievementses)
|
||||
res.status(200).send((achievement.toObject({req: req}) for achievement in achievements))
|
||||
|
||||
fetchRelatedLevels: wrap (req, res) ->
|
||||
campaign = yield database.getDocFromHandle(req, Campaign)
|
||||
if not campaign
|
||||
throw new errors.NotFound('Campaign not found.')
|
||||
levels = campaign.get('levels') or []
|
||||
project = parse.getProjectFromReq(req)
|
||||
sort = { 'version.major': -1, 'version.minor': -1 }
|
||||
fetches = []
|
||||
for level in _.values(levels)
|
||||
query = { original: mongoose.Types.ObjectId(level.original) }
|
||||
fetches.push Level.findOne(query).sort(sort).select(project)
|
||||
levels = yield fetches
|
||||
res.status(200).send((level.toObject({req: req}) for level in levels))
|
||||
|
||||
fetchOverworld: wrap (req, res) ->
|
||||
project = parse.getProjectFromReq(req)
|
||||
campaigns = yield Campaign.find({type: 'hero'}).select(project)
|
||||
formatCampaign = (campaign) ->
|
||||
campaign.toObject({req: req})
|
||||
campaign.adjacentCampaigns = _.mapValues(campaign.adjacentCampaigns, (a) ->
|
||||
_.pick(a, ['showIfUnlocked', 'color', 'name', 'description' ]))
|
||||
for original, level of campaign.levels
|
||||
campaign.levels[original] = _.pick level, ['locked', 'disabled', 'original', 'rewards', 'slug']
|
||||
return campaign
|
||||
res.status(200).send((formatCampaign(campaign) for campaign in campaigns))
|
|
@ -42,8 +42,17 @@ module.exports.setup = (app) ->
|
|||
app.post('/db/article/:handle/watchers', mw.patchable.joinWatchers(Article))
|
||||
app.delete('/db/article/:handle/watchers', mw.patchable.leaveWatchers(Article))
|
||||
|
||||
app.get('/db/campaign', mw.campaigns.fetchByType)
|
||||
Campaign = require '../models/Campaign'
|
||||
app.post('/db/campaign', mw.auth.checkHasPermission(['admin']), mw.rest.post(Campaign))
|
||||
app.get('/db/campaign', mw.campaigns.fetchByType, mw.rest.get(Campaign))
|
||||
app.get('/db/campaign/names', mw.named.names(Campaign))
|
||||
app.post('/db/campaign/names', mw.named.names(Campaign))
|
||||
app.get('/db/campaign/:handle', mw.rest.getByHandle(Campaign))
|
||||
app.put('/db/campaign/:handle', mw.campaigns.put)
|
||||
app.get('/db/campaign/:handle/achievements', mw.campaigns.fetchRelatedAchievements)
|
||||
app.get('/db/campaign/:handle/levels', mw.campaigns.fetchRelatedLevels)
|
||||
app.get('/db/campaign/:handle/patches', mw.patchable.patches(Campaign))
|
||||
app.get('/db/campaign/-/overworld', mw.campaigns.fetchOverworld)
|
||||
|
||||
app.post('/db/classroom', mw.classrooms.post)
|
||||
app.get('/db/classroom', mw.classrooms.getByOwner)
|
||||
|
|
204
spec/server/functional/campaign.spec.coffee
Normal file
204
spec/server/functional/campaign.spec.coffee
Normal file
|
@ -0,0 +1,204 @@
|
|||
require '../common'
|
||||
|
||||
campaignURL = getURL('/db/campaign')
|
||||
campaignSchema = require '../../../app/schemas/models/campaign.schema'
|
||||
campaignLevelProperties = _.keys(campaignSchema.properties.levels.additionalProperties.properties)
|
||||
Achievement = require '../../../server/models/Achievement'
|
||||
Campaign = require '../../../server/models/Campaign'
|
||||
Level = require '../../../server/models/Level'
|
||||
User = require '../../../server/models/User'
|
||||
request = require '../request'
|
||||
utils = require '../utils'
|
||||
slack = require '../../../server/slack'
|
||||
Promise = require 'bluebird'
|
||||
|
||||
|
||||
describe 'GET /db/campaign', ->
|
||||
|
||||
beforeEach utils.wrap (done) ->
|
||||
yield utils.clearModels([Campaign])
|
||||
@heroCampaign1 = yield new Campaign({name: 'Hero Campaign 1', type: 'hero'}).save()
|
||||
@heroCampaign2 = yield new Campaign({name: 'Hero Campaign 2', type: 'hero'}).save()
|
||||
@courseCampaign1 = yield new Campaign({name: 'Course Campaign 1', type: 'course'}).save()
|
||||
@courseCampaign2 = yield new Campaign({name: 'Course Campaign 2', type: 'course'}).save()
|
||||
done()
|
||||
|
||||
it 'returns all campaigns', utils.wrap (done) ->
|
||||
[res, body] = yield request.getAsync getURL('/db/campaign'), { json: true }
|
||||
expect(res.statusCode).toBe(200)
|
||||
expect(body.length).toBe(4)
|
||||
done()
|
||||
|
||||
describe 'with GET query param type', ->
|
||||
it 'returns campaigns of that type', utils.wrap (done) ->
|
||||
[res, body] = yield request.getAsync getURL('/db/campaign?type=course'), { json: true }
|
||||
expect(res.statusCode).toBe(200)
|
||||
expect(body.length).toBe(2)
|
||||
for campaign in body
|
||||
expect(campaign.type).toBe('course')
|
||||
done()
|
||||
|
||||
|
||||
describe 'POST /db/campaign', ->
|
||||
beforeEach utils.wrap (done) ->
|
||||
yield utils.clearModels [Campaign, Level, User]
|
||||
admin = yield utils.initAdmin()
|
||||
yield utils.loginUser(admin)
|
||||
@levels = (level.toObject() for level in [yield utils.makeLevel(), yield utils.makeLevel()])
|
||||
done()
|
||||
|
||||
it 'can create campaigns', utils.wrap (done) ->
|
||||
campaign = {
|
||||
levels: {}
|
||||
}
|
||||
for level in @levels.reverse()
|
||||
campaign.levels[level.original.valueOf()] = _.pick level, campaignLevelProperties
|
||||
[res, body] = yield request.postAsync {uri: campaignURL, json: campaign}
|
||||
expect(res.statusCode).toBe(201)
|
||||
campaign = body
|
||||
done()
|
||||
|
||||
describe 'PUT /db/campaign/:handle', ->
|
||||
beforeEach utils.wrap (done) ->
|
||||
yield utils.clearModels [Achievement, Campaign, Level, User]
|
||||
admin = yield utils.initAdmin()
|
||||
yield utils.loginUser(admin)
|
||||
@campaign = yield utils.makeCampaign()
|
||||
@levelsUpdated = @campaign.get('levelsUpdated').toISOString()
|
||||
done()
|
||||
|
||||
it 'saves changes to campaigns', utils.wrap (done) ->
|
||||
[res, body] = yield request.putAsync { uri: campaignURL+'/'+@campaign.id, json: { name: 'A new name' } }
|
||||
expect(body.name).toBe('A new name')
|
||||
c = yield Campaign.findById(body._id)
|
||||
expect(c.get('name')).toBe('A new name')
|
||||
done()
|
||||
|
||||
it 'does not allow normal users to make changes', utils.wrap (done) ->
|
||||
user = yield utils.initUser()
|
||||
yield utils.loginUser(user)
|
||||
[res, body] = yield request.putAsync { uri: campaignURL+'/'+@campaign.id, json: { name: 'A new name' } }
|
||||
expect(res.statusCode).toBe(403)
|
||||
done()
|
||||
|
||||
it 'allows normal users to put translation changes', utils.wrap (done) ->
|
||||
user = yield utils.initUser()
|
||||
yield utils.logout()
|
||||
yield utils.loginUser(user)
|
||||
json = _.clone @campaign.toObject()
|
||||
json.i18n = { de: { name: 'A new name' } }
|
||||
[res, body] = yield request.putAsync { uri: campaignURL+'/'+@campaign.id, json: json }
|
||||
expect(res.statusCode).toBe(200)
|
||||
done()
|
||||
|
||||
it 'sends a slack message', utils.wrap (done) ->
|
||||
spyOn(slack, 'sendSlackMessage')
|
||||
[res, body] = yield request.putAsync { uri: campaignURL+'/'+@campaign.id, json: { name: 'A new name' } }
|
||||
expect(slack.sendSlackMessage).toHaveBeenCalled()
|
||||
done()
|
||||
|
||||
it 'sets campaign.levelsUpdated to now iff levels are changed', utils.wrap (done) ->
|
||||
data = {name: 'whatever'}
|
||||
[res, body] = yield request.putAsync { uri: campaignURL+'/'+@campaign.id, json: data }
|
||||
expect(body.levelsUpdated).toBe(@levelsUpdated)
|
||||
yield new Promise((resolve) -> setTimeout(resolve, 10))
|
||||
data = {levels: {'a': {original: 'a'}}}
|
||||
[res, body] = yield request.putAsync { uri: campaignURL+'/'+@campaign.id, json: data }
|
||||
expect(body.levelsUpdated).not.toBe(@levelsUpdated)
|
||||
done()
|
||||
|
||||
|
||||
describe 'GET, POST /db/campaign/names', ->
|
||||
beforeEach utils.wrap (done) ->
|
||||
yield utils.clearModels [Achievement, Campaign, Level, User]
|
||||
admin = yield utils.initAdmin()
|
||||
yield utils.loginUser(admin)
|
||||
@campaignA = yield utils.makeCampaign()
|
||||
@campaignB = yield utils.makeCampaign()
|
||||
done()
|
||||
|
||||
it 'returns names of campaigns by for given ids', utils.wrap (done) ->
|
||||
[res, body] = yield request.getAsync({url: getURL("/db/campaign/names?ids=#{@campaignA.id},#{@campaignB.id}"), json: true})
|
||||
expect(res.statusCode).toBe(200)
|
||||
expect(body.length).toBe(2)
|
||||
[res, body] = yield request.postAsync({url: getURL('/db/campaign/names'), json: { ids: [@campaignA.id, @campaignB.id] }})
|
||||
expect(res.statusCode).toBe(200)
|
||||
expect(body.length).toBe(2)
|
||||
done()
|
||||
|
||||
|
||||
describe 'GET /db/campaign/:handle/levels', ->
|
||||
beforeEach utils.wrap (done) ->
|
||||
yield utils.clearModels [Campaign, Level, User]
|
||||
admin = yield utils.initAdmin()
|
||||
yield utils.loginUser(admin)
|
||||
@level1 = yield utils.makeLevel()
|
||||
@level2 = yield utils.makeLevel()
|
||||
@campaign = yield utils.makeCampaign({}, {levels: [@level1, @level2]})
|
||||
done()
|
||||
|
||||
it 'fetches the levels in a campaign', utils.wrap (done) ->
|
||||
url = getURL("/db/campaign/#{@campaign._id}/levels")
|
||||
[res, body] = yield request.getAsync {uri: url, json: true}
|
||||
expect(res.statusCode).toBe(200)
|
||||
expect(body.length).toBe(2)
|
||||
expect(_.difference([@level1.get('slug'), @level2.get('slug')], _.pluck(body, 'slug')).length).toBe(0)
|
||||
done()
|
||||
|
||||
describe 'GET /db/campaign/:handle/achievements', ->
|
||||
beforeEach utils.wrap (done) ->
|
||||
yield utils.clearModels [Achievement, Campaign, Level, User]
|
||||
admin = yield utils.initAdmin()
|
||||
yield utils.loginUser(admin)
|
||||
level = yield utils.makeLevel()
|
||||
@achievement = yield utils.makeAchievement({}, {related: level})
|
||||
@campaign = yield utils.makeCampaign({}, {levels: [level]})
|
||||
done()
|
||||
|
||||
it 'fetches the achievements in the levels in a campaign', utils.wrap (done) ->
|
||||
url = getURL("/db/campaign/#{@campaign.id}/achievements")
|
||||
[res, body] = yield request.getAsync {uri: url, json: true}
|
||||
expect(res.statusCode).toBe(200)
|
||||
expect(body.length).toBe(1)
|
||||
done()
|
||||
|
||||
describe 'GET /db/campaign/-/overworld', ->
|
||||
beforeEach utils.wrap (done) ->
|
||||
yield utils.clearModels [Campaign, Level, User]
|
||||
admin = yield utils.initAdmin()
|
||||
yield utils.loginUser(admin)
|
||||
level = yield utils.makeLevel()
|
||||
@campaignA = yield utils.makeCampaign({type: 'hero', hidesHUD: true})
|
||||
@campaignB = yield utils.makeCampaign({type: 'hero'}, {
|
||||
levels: [level]
|
||||
adjacentCampaigns: [@campaignA]
|
||||
})
|
||||
@campaignC = yield utils.makeCampaign({type: 'course'})
|
||||
done()
|
||||
|
||||
it 'fetches campaigns of type "hero", returning projected level and adjacentCampaign children', utils.wrap (done) ->
|
||||
url = getURL("/db/campaign/-/overworld")
|
||||
[res, body] = yield request.getAsync {uri: url, json: true}
|
||||
expect(res.statusCode).toBe(200)
|
||||
expect(body.length).toBe(2)
|
||||
for campaign in body
|
||||
expect(campaign.type).toBe('hero')
|
||||
|
||||
campaign = _.findWhere(body, {_id: @campaignB.id})
|
||||
expect(_.size(campaign.levels)).toBeGreaterThan(0)
|
||||
for level in _.values(campaign.levels)
|
||||
expect(level.slug).toBeDefined()
|
||||
expect(_.size(campaign.adjacentCampaigns)).toBeGreaterThan(0)
|
||||
for campaign in _.values(campaign.adjacentCampaigns)
|
||||
expect(campaign.name).toBeDefined()
|
||||
done()
|
||||
|
||||
it 'takes a project query param', utils.wrap (done) ->
|
||||
url = getURL("/db/campaign/-/overworld?project=name")
|
||||
[res, body] = yield request.getAsync {uri: url, json: true}
|
||||
expect(res.statusCode).toBe(200)
|
||||
expect(body.length).toBe(2)
|
||||
for campaign in body
|
||||
expect(campaign.type).toBeUndefined()
|
||||
expect(campaign.name).toBeDefined()
|
||||
done()
|
|
@ -1,134 +0,0 @@
|
|||
require '../common'
|
||||
|
||||
levels = [
|
||||
{
|
||||
name: 'Level 1'
|
||||
description: 'This is the first level.'
|
||||
disableSpaces: true
|
||||
icon: 'somestringyoudontneed.png'
|
||||
}
|
||||
{
|
||||
name: 'Level 2'
|
||||
description: 'This is the second level.'
|
||||
requiresSubscription: true
|
||||
backspaceThrottle: true
|
||||
}
|
||||
]
|
||||
|
||||
achievement = {
|
||||
name: 'Level 1 Complete'
|
||||
}
|
||||
|
||||
campaign = {
|
||||
name: 'Campaign'
|
||||
levels: {}
|
||||
i18n: {}
|
||||
}
|
||||
|
||||
levelURL = getURL('/db/level')
|
||||
achievementURL = getURL('/db/achievement')
|
||||
campaignURL = getURL('/db/campaign')
|
||||
campaignSchema = require '../../../app/schemas/models/campaign.schema'
|
||||
campaignLevelProperties = _.keys(campaignSchema.properties.levels.additionalProperties.properties)
|
||||
Achievement = require '../../../server/models/Achievement'
|
||||
Campaign = require '../../../server/models/Campaign'
|
||||
Level = require '../../../server/models/Level'
|
||||
User = require '../../../server/models/User'
|
||||
request = require '../request'
|
||||
utils = require '../utils'
|
||||
slack = require '../../../server/slack'
|
||||
Promise = require 'bluebird'
|
||||
|
||||
describe 'PUT /db/campaign', ->
|
||||
beforeEach utils.wrap (done) ->
|
||||
yield utils.clearModels [Achievement, Campaign, Level, User]
|
||||
admin = yield utils.initAdmin()
|
||||
yield utils.loginUser(admin)
|
||||
[res, body] = yield request.postAsync { uri: campaignURL, json: campaign }
|
||||
@levelsUpdated = body.levelsUpdated
|
||||
@campaign = yield Campaign.findById(body._id)
|
||||
done()
|
||||
|
||||
it 'saves changes to campaigns', utils.wrap (done) ->
|
||||
[res, body] = yield request.putAsync { uri: campaignURL+'/'+@campaign.id, json: { name: 'A new name' } }
|
||||
expect(body.name).toBe('A new name')
|
||||
c = yield Campaign.findById(body._id)
|
||||
expect(c.get('name')).toBe('A new name')
|
||||
done()
|
||||
|
||||
it 'does not allow normal users to make changes', utils.wrap (done) ->
|
||||
user = yield utils.initUser()
|
||||
yield utils.loginUser(user)
|
||||
[res, body] = yield request.putAsync { uri: campaignURL+'/'+@campaign.id, json: { name: 'A new name' } }
|
||||
expect(res.statusCode).toBe(403)
|
||||
done()
|
||||
|
||||
it 'allows normal users to put translation changes', utils.wrap (done) ->
|
||||
user = yield utils.initUser()
|
||||
yield utils.loginUser(user)
|
||||
json = _.clone @campaign.toObject()
|
||||
json.i18n = { de: { name: 'A new name' } }
|
||||
[res, body] = yield request.putAsync { uri: campaignURL+'/'+@campaign.id, json: json }
|
||||
expect(res.statusCode).toBe(200)
|
||||
done()
|
||||
|
||||
it 'sends a slack message', utils.wrap (done) ->
|
||||
spyOn(slack, 'sendSlackMessage')
|
||||
[res, body] = yield request.putAsync { uri: campaignURL+'/'+@campaign.id, json: { name: 'A new name' } }
|
||||
expect(slack.sendSlackMessage).toHaveBeenCalled()
|
||||
done()
|
||||
|
||||
it 'sets campaign.levelsUpdated to now iff levels are changed', utils.wrap (done) ->
|
||||
data = {name: 'whatever'}
|
||||
[res, body] = yield request.putAsync { uri: campaignURL+'/'+@campaign.id, json: data }
|
||||
expect(body.levelsUpdated).toBe(@levelsUpdated)
|
||||
yield new Promise((resolve) -> setTimeout(resolve, 10))
|
||||
data = {levels: {'a': {original: 'a'}}}
|
||||
[res, body] = yield request.putAsync { uri: campaignURL+'/'+@campaign.id, json: data }
|
||||
expect(body.levelsUpdated).not.toBe(@levelsUpdated)
|
||||
done()
|
||||
|
||||
describe '/db/campaign', ->
|
||||
it 'prepares the db first', (done) ->
|
||||
clearModels [Achievement, Campaign, Level, User], (err) ->
|
||||
expect(err).toBeNull()
|
||||
loginAdmin (admin) ->
|
||||
levels[0].permissions = levels[1].permissions = [{target: admin._id, access: 'owner'}]
|
||||
request.post {uri: levelURL, json: levels[0]}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
levels[0] = body
|
||||
request.post {uri: levelURL, json: levels[1]}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
levels[1] = body
|
||||
achievement.related = levels[0].original
|
||||
achievement.rewards = { levels: [levels[1].original] }
|
||||
request.post {uri: achievementURL, json: achievement}, (err, res, body) ->
|
||||
achievement = body
|
||||
done()
|
||||
|
||||
it 'can create campaigns', (done) ->
|
||||
for level in levels.reverse()
|
||||
campaign.levels[level.original] = _.pick level, campaignLevelProperties
|
||||
request.post {uri: campaignURL, json: campaign}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
campaign = body
|
||||
done()
|
||||
|
||||
describe '/db/campaign/.../levels', ->
|
||||
it 'fetches the levels in a campaign', (done) ->
|
||||
url = getURL("/db/campaign/#{campaign._id}/levels")
|
||||
request.get {uri: url}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
body = JSON.parse(body)
|
||||
expect(body.length).toBe(2)
|
||||
expect(_.difference(['level-1', 'level-2'],(level.slug for level in body)).length).toBe(0)
|
||||
done()
|
||||
|
||||
describe '/db/campaign/.../achievements', ->
|
||||
it 'fetches the achievements in the levels in a campaign', (done) ->
|
||||
url = getURL("/db/campaign/#{campaign._id}/achievements")
|
||||
request.get {uri: url}, (err, res, body) ->
|
||||
expect(res.statusCode).toBe(200)
|
||||
body = JSON.parse(body)
|
||||
expect(body.length).toBe(1)
|
||||
done()
|
|
@ -1,38 +0,0 @@
|
|||
config = require '../../../server_config'
|
||||
require '../common'
|
||||
clientUtils = require '../../../app/core/utils' # Must come after require /common
|
||||
utils = require '../utils'
|
||||
_ = require 'lodash'
|
||||
Promise = require 'bluebird'
|
||||
request = require '../request'
|
||||
requestAsync = Promise.promisify(request, {multiArgs: true})
|
||||
|
||||
campaignURL = getURL('/db/campaign')
|
||||
|
||||
Campaign = require '../../../server/models/Campaign'
|
||||
|
||||
describe '/db/campaign', ->
|
||||
|
||||
beforeEach utils.wrap (done) ->
|
||||
yield utils.clearModels([Campaign])
|
||||
@heroCampaign1 = yield new Campaign({name: 'Hero Campaign 1', type: 'hero'}).save()
|
||||
@heroCampaign2 = yield new Campaign({name: 'Hero Campaign 2', type: 'hero'}).save()
|
||||
@courseCampaign1 = yield new Campaign({name: 'Course Campaign 1', type: 'course'}).save()
|
||||
@courseCampaign2 = yield new Campaign({name: 'Course Campaign 2', type: 'course'}).save()
|
||||
done()
|
||||
|
||||
describe 'GET campaigns of a certain type', ->
|
||||
it 'returns only that type', utils.wrap (done) ->
|
||||
[res, body] = yield request.getAsync getURL('/db/campaign?type=course'), { json: true }
|
||||
expect(res.statusCode).toBe(200)
|
||||
expect(body.length).toBe(2)
|
||||
for campaign in body
|
||||
expect(campaign.type).toBe('course')
|
||||
done()
|
||||
|
||||
describe 'GET all campaigns', ->
|
||||
it 'returns all of them regardless of type', utils.wrap (done) ->
|
||||
[res, body] = yield request.getAsync getURL('/db/campaign'), { json: true }
|
||||
expect(res.statusCode).toBe(200)
|
||||
expect(body.length).toBe(4)
|
||||
done()
|
|
@ -20,7 +20,7 @@ describe 'Level', ->
|
|||
urlLevel = '/db/level'
|
||||
|
||||
it 'clears things first', (done) ->
|
||||
clearModels [Level], (err) ->
|
||||
clearModels [Level, User], (err) ->
|
||||
expect(err).toBeNull()
|
||||
done()
|
||||
|
||||
|
|
|
@ -3,7 +3,12 @@ utils = require '../../server/lib/utils'
|
|||
co = require 'co'
|
||||
Promise = require 'bluebird'
|
||||
User = require '../../server/models/User'
|
||||
|
||||
Level = require '../../server/models/Level'
|
||||
Achievement = require '../../server/models/Achievement'
|
||||
Campaign = require '../../server/models/Campaign'
|
||||
campaignSchema = require '../../app/schemas/models/campaign.schema'
|
||||
campaignLevelProperties = _.keys(campaignSchema.properties.levels.additionalProperties.properties)
|
||||
campaignAdjacentCampaignProperties = _.keys(campaignSchema.properties.adjacentCampaigns.additionalProperties.properties)
|
||||
|
||||
module.exports = mw =
|
||||
getURL: (path) -> 'http://localhost:3001' + path
|
||||
|
@ -32,7 +37,7 @@ module.exports = mw =
|
|||
promise = user.save()
|
||||
return promise
|
||||
|
||||
loginUser: Promise.promisify (user, options={}, done) ->
|
||||
loginUser: Promise.promisify (user, options={}, done) ->
|
||||
if _.isFunction(options)
|
||||
done = options
|
||||
options = {}
|
||||
|
@ -43,6 +48,7 @@ module.exports = mw =
|
|||
(options.request or request).post mw.getURL('/auth/login'), { form: form }, (err, res) ->
|
||||
expect(err).toBe(null)
|
||||
expect(res.statusCode).toBe(200)
|
||||
mw.lastLogin = user
|
||||
done(err, user)
|
||||
|
||||
initAdmin: (options) ->
|
||||
|
@ -70,4 +76,52 @@ module.exports = mw =
|
|||
fn = co.wrap(gen)
|
||||
return (done) ->
|
||||
fn.apply(@, [done]).catch (err) -> done.fail(err)
|
||||
|
||||
|
||||
makeLevel: Promise.promisify (data, sources, done) ->
|
||||
args = Array.from(arguments)
|
||||
[done, [data, sources]] = [args.pop(), args]
|
||||
|
||||
data = _.extend({}, {
|
||||
name: _.uniqueId('Level ')
|
||||
permissions: [{target: mw.lastLogin.id, access: 'owner'}]
|
||||
}, data)
|
||||
|
||||
request.post { uri: getURL('/db/level'), json: data }, (err, res) ->
|
||||
return done(err) if err
|
||||
Level.findById(res.body._id).exec done
|
||||
|
||||
makeAchievement: Promise.promisify (data, sources, done) ->
|
||||
args = Array.from(arguments)
|
||||
[done, [data, sources]] = [args.pop(), args]
|
||||
|
||||
data = _.extend({}, {
|
||||
name: _.uniqueId('Achievement ')
|
||||
}, data)
|
||||
if sources.related and not data.related
|
||||
related = sources.related
|
||||
data.related = (related.get('original') or related._id).valueOf()
|
||||
|
||||
request.post { uri: getURL('/db/achievement'), json: data }, (err, res) ->
|
||||
return done(err) if err
|
||||
Achievement.findById(res.body._id).exec done
|
||||
|
||||
makeCampaign: Promise.promisify (data, sources, done) ->
|
||||
args = Array.from(arguments)
|
||||
[done, [data, sources]] = [args.pop(), args]
|
||||
|
||||
data = _.extend({}, {
|
||||
name: _.uniqueId('Campaign ')
|
||||
}, data)
|
||||
if not data.levels
|
||||
data.levels = {}
|
||||
for level in sources?.levels or []
|
||||
data.levels[level.get('original').valueOf()] = _.pick level.toObject(), campaignLevelProperties
|
||||
|
||||
if not data.adjacentCampaigns
|
||||
data.adjacentCampaigns = {}
|
||||
for campaign in sources?.adjacentCampaigns or []
|
||||
data.adjacentCampaigns[campaign.id] = _.pick campaign.toObject(), campaignAdjacentCampaignProperties
|
||||
|
||||
request.post { uri: getURL('/db/campaign'), json: data }, (err, res) ->
|
||||
return done(err) if err
|
||||
Campaign.findById(res.body._id).exec done
|
Loading…
Add table
Reference in a new issue