mirror of
https://github.com/sudoxnym/habitica.git
synced 2026-05-20 20:58:51 +00:00
Merge pull request #5934 from HabitRPG/adjustments_to_group_front_end_only
Adjustments to group quest behavior
This commit is contained in:
commit
f71e3e20eb
14 changed files with 866 additions and 354 deletions
14
package.json
14
package.json
|
|
@ -20,6 +20,7 @@
|
|||
"express-csv": "~0.6.0",
|
||||
"firebase": "^2.2.9",
|
||||
"firebase-token-generator": "^2.0.0",
|
||||
"glob": "^4.3.5",
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-browserify": "^3.3.0",
|
||||
"grunt-cli": "~0.1.9",
|
||||
|
|
@ -32,7 +33,11 @@
|
|||
"grunt-hashres": "~0.4.1",
|
||||
"grunt-karma": "~0.6.2",
|
||||
"gulp": "^3.9.0",
|
||||
"gulp-clean": "^0.3.1",
|
||||
"gulp-grunt": "^0.5.2",
|
||||
"gulp-imagemin": "^2.3.0",
|
||||
"gulp-nodemon": "^2.0.4",
|
||||
"gulp.spritesmith": "^4.1.0",
|
||||
"icalendar": "lefnire/node-icalendar#e06da0e55901f0ba940dfadc42c158ed0b1fead9",
|
||||
"image-size": "~0.3.2",
|
||||
"in-app-purchase": "^0.2.0",
|
||||
|
|
@ -41,6 +46,7 @@
|
|||
"lodash": "~2.4.1",
|
||||
"loggly": "~1.0.8",
|
||||
"marked": "^0.3.5",
|
||||
"merge-stream": "^1.0.0",
|
||||
"method-override": "~2.2.0",
|
||||
"moment": "~2.8.3",
|
||||
"mongoose": "~3.8.23",
|
||||
|
|
@ -62,6 +68,7 @@
|
|||
"request": "~2.44.0",
|
||||
"s3-upload-stream": "^1.0.6",
|
||||
"stripe": "*",
|
||||
"superagent": "~0.15.7",
|
||||
"swagger-node-express": "lefnire/swagger-node-express#habitrpg",
|
||||
"universal-analytics": "~0.3.2",
|
||||
"validator": "~3.19.0",
|
||||
|
|
@ -93,11 +100,6 @@
|
|||
"deep-diff": "~0.1.4",
|
||||
"event-stream": "^3.2.2",
|
||||
"expect.js": "~0.2.0",
|
||||
"glob": "^4.3.5",
|
||||
"gulp-clean": "^0.3.1",
|
||||
"gulp-imagemin": "^2.3.0",
|
||||
"gulp-nodemon": "^2.0.4",
|
||||
"gulp.spritesmith": "^4.1.0",
|
||||
"istanbul": "^0.3.14",
|
||||
"karma": "~0.10.2",
|
||||
"karma-chai-plugins": "~0.1.0",
|
||||
|
|
@ -114,7 +116,6 @@
|
|||
"karma-requirejs": "~0.2.0",
|
||||
"karma-script-launcher": "~0.1.0",
|
||||
"lcov-result-merger": "^1.0.2",
|
||||
"merge-stream": "^1.0.0",
|
||||
"mocha": "~1.12.1",
|
||||
"mongoskin": "~0.6.1",
|
||||
"protractor": "~2.0.0",
|
||||
|
|
@ -122,7 +123,6 @@
|
|||
"shelljs": "^0.4.0",
|
||||
"sinon": "1.15.4",
|
||||
"sinon-chai": "^2.7.0",
|
||||
"superagent": "~0.15.7",
|
||||
"superagent-defaults": "~0.1.5",
|
||||
"vinyl-source-stream": "^1.0.0",
|
||||
"vinyl-transform": "^1.0.0"
|
||||
|
|
|
|||
|
|
@ -151,6 +151,7 @@ describe('Groups Controller', function() {
|
|||
'another-user'
|
||||
],
|
||||
save: sinon.stub().yields(),
|
||||
leave: sinon.stub().yields(),
|
||||
markModified: sinon.spy()
|
||||
};
|
||||
|
||||
|
|
@ -177,54 +178,67 @@ describe('Groups Controller', function() {
|
|||
context('party', function() {
|
||||
beforeEach(function() {
|
||||
group.type = 'party';
|
||||
});
|
||||
|
||||
it('prevents user from leaving party if quest is active and part of the active members list', function() {
|
||||
group.quest = {
|
||||
leader : 'another-user',
|
||||
active: true,
|
||||
members: {
|
||||
'user-id': true,
|
||||
'another-user': true
|
||||
},
|
||||
key : 'vice1',
|
||||
progress : {
|
||||
hp : 364,
|
||||
collect : {}
|
||||
another_user: true,
|
||||
yet_another_user: null,
|
||||
'user-id': true
|
||||
}
|
||||
};
|
||||
|
||||
sinon.spy(Group, 'update');
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
Group.update.restore();
|
||||
});
|
||||
|
||||
it('prevents user from leaving party if quest is active', function() {
|
||||
user.party = {
|
||||
quest : {
|
||||
key : 'vice1',
|
||||
progress : {
|
||||
up : 50,
|
||||
down : 0,
|
||||
collect : {}
|
||||
},
|
||||
completed : null,
|
||||
RSVPNeeded : false
|
||||
}
|
||||
}
|
||||
|
||||
groupsController.leave(req, res);
|
||||
|
||||
expect(Group.update).to.not.be.called;
|
||||
expect(group.leave).to.not.be.called;
|
||||
expect(res.json).to.be.calledOnce;
|
||||
expect(res.json).to.be.calledWith(403, 'You cannot leave party during an active quest. Please leave the quest first');
|
||||
});
|
||||
|
||||
it('leaves party if quest is not active', function() {
|
||||
user.party = { quest: { key: null } };
|
||||
it('prevents quest leader from leaving a party if they have started a quest', function() {
|
||||
group.quest = {
|
||||
active: false,
|
||||
leader: 'user-id'
|
||||
};
|
||||
|
||||
groupsController.leave(req, res);
|
||||
|
||||
expect(Group.update).to.be.calledOnce;
|
||||
expect(group.leave).to.not.be.called;
|
||||
expect(res.json).to.be.calledOnce;
|
||||
expect(res.json).to.be.calledWith(403, 'You cannot leave your party when you have started a quest. Abort the quest first.');
|
||||
});
|
||||
|
||||
it('leaves party if quest is not active', function() {
|
||||
group.quest = {
|
||||
active: false,
|
||||
members: {
|
||||
another_user: true,
|
||||
yet_another_user: null,
|
||||
'user-id': null
|
||||
}
|
||||
};
|
||||
|
||||
groupsController.leave(req, res);
|
||||
|
||||
expect(group.leave).to.be.calledOnce;
|
||||
expect(res.json).to.not.be.called;
|
||||
});
|
||||
|
||||
it('leaves party if quest is active, but user is not part of quest', function() {
|
||||
group.quest = {
|
||||
active: true,
|
||||
members: {
|
||||
another_user: true,
|
||||
yet_another_user: null,
|
||||
'user-id': null
|
||||
}
|
||||
};
|
||||
|
||||
groupsController.leave(req, res);
|
||||
|
||||
expect(group.leave).to.be.calledOnce;
|
||||
expect(res.json).to.not.be.called;
|
||||
});
|
||||
});
|
||||
|
|
@ -379,4 +393,105 @@ describe('Groups Controller', function() {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#removeMember', function() {
|
||||
var req, res, group, user;
|
||||
|
||||
beforeEach(function() {
|
||||
user = { _id: 'user-id' };
|
||||
group = {
|
||||
_id: 'group-id',
|
||||
leader: 'user-id',
|
||||
members: ['user-id', 'member-to-boot', 'another-user']
|
||||
}
|
||||
res = {
|
||||
locals: {
|
||||
user: user,
|
||||
group: group
|
||||
},
|
||||
send: sinon.stub()
|
||||
};
|
||||
req = {
|
||||
query: {
|
||||
uuid: 'member-to-boot'
|
||||
}
|
||||
};
|
||||
|
||||
sinon.stub(Group, 'update');
|
||||
sinon.stub(User, 'update');
|
||||
sinon.stub(User, 'findById');
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
Group.update.restore();
|
||||
User.update.restore();
|
||||
User.findById.restore();
|
||||
});
|
||||
|
||||
context('quest behavior', function() {
|
||||
it('removes quest from party if booted member was quest leader', function() {
|
||||
group.quest = {
|
||||
leader: 'member-to-boot',
|
||||
active: true,
|
||||
members: {
|
||||
'user-id': true,
|
||||
'leader-id': true,
|
||||
'member-to-boot': true
|
||||
},
|
||||
key: 'whale'
|
||||
}
|
||||
|
||||
groupsController.removeMember(req, res);
|
||||
|
||||
expect(Group.update).to.be.calledOnce;
|
||||
expect(Group.update).to.be.calledWith(
|
||||
{ _id: 'group-id'},
|
||||
{
|
||||
'$inc': { memberCount: -1 },
|
||||
'$pull': { members: 'member-to-boot' },
|
||||
'$set': { quest: {key: null, leader: null} }
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('returns quest scroll to booted member if booted member was leader of quest', function() {
|
||||
Group.update.yields();
|
||||
var bootedMember = {
|
||||
_id: 'member-to-boot',
|
||||
apiToken: 'api',
|
||||
preferences: {
|
||||
emailNotifications: {
|
||||
kickedGroup: false
|
||||
}
|
||||
}
|
||||
};
|
||||
User.findById.yields(null, bootedMember);
|
||||
User.update.returns({
|
||||
exec: sinon.stub()
|
||||
});
|
||||
|
||||
group.quest = {
|
||||
leader: 'member-to-boot',
|
||||
active: true,
|
||||
members: {
|
||||
'user-id': true,
|
||||
'leader-id': true,
|
||||
'member-to-boot': true
|
||||
},
|
||||
key: 'whale'
|
||||
}
|
||||
|
||||
groupsController.removeMember(req, res);
|
||||
|
||||
expect(User.update).to.be.calledOnce;
|
||||
expect(User.update).to.be.calledWith(
|
||||
{ _id: 'member-to-boot', apiToken: 'api' },
|
||||
{
|
||||
'$unset': { 'newMessages.group-id': ''},
|
||||
'$inc': { 'items.quests.whale': 1 }
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -157,6 +157,72 @@ describe('Inventory Controller', function() {
|
|||
});
|
||||
});
|
||||
|
||||
describe('#buyQuest', function() {
|
||||
var quests, questObject;
|
||||
|
||||
beforeEach(inject(function(Quests) {
|
||||
quests = Quests;
|
||||
questObject = { key: 'whale' };
|
||||
|
||||
sandbox.stub(quests, 'buyQuest').returns({ then: function(res) { res(questObject); } });
|
||||
}));
|
||||
|
||||
it('calls Quests.buyQuest', function() {
|
||||
scope.buyQuest('foo');
|
||||
|
||||
expect(quests.buyQuest).to.be.calledOnce;
|
||||
expect(quests.buyQuest).to.be.calledWith('foo');
|
||||
});
|
||||
|
||||
it('sets selectedQuest to resolved quest object', function() {
|
||||
scope.buyQuest('whale');
|
||||
|
||||
expect(rootScope.selectedQuest).to.eql(questObject);
|
||||
});
|
||||
|
||||
it('opens buyQuest modal', function() {
|
||||
sandbox.spy(rootScope, 'openModal');
|
||||
|
||||
scope.buyQuest('whale');
|
||||
|
||||
expect(rootScope.openModal).to.be.calledOnce;
|
||||
expect(rootScope.openModal).to.be.calledWith('buyQuest', {controller: 'InventoryCtrl'});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#showQuest', function() {
|
||||
var quests, questObject;
|
||||
|
||||
beforeEach(inject(function(Quests) {
|
||||
quests = Quests;
|
||||
questObject = { key: 'whale' };
|
||||
|
||||
sandbox.stub(quests, 'showQuest').returns({ then: function(res) { res(questObject); } });
|
||||
}));
|
||||
|
||||
it('calls Quests.showQuest', function() {
|
||||
scope.showQuest('foo');
|
||||
|
||||
expect(quests.showQuest).to.be.calledOnce;
|
||||
expect(quests.showQuest).to.be.calledWith('foo');
|
||||
});
|
||||
|
||||
it('sets selectedQuest to resolved quest object', function() {
|
||||
scope.showQuest('whale');
|
||||
|
||||
expect(rootScope.selectedQuest).to.eql(questObject);
|
||||
});
|
||||
|
||||
it('opens showQuest modal', function() {
|
||||
sandbox.spy(rootScope, 'openModal');
|
||||
|
||||
scope.showQuest('whale');
|
||||
|
||||
expect(rootScope.openModal).to.be.calledOnce;
|
||||
expect(rootScope.openModal).to.be.calledWith('showQuest', {controller: 'InventoryCtrl'});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#hasAllTimeTravelerItems', function() {
|
||||
it('returns false if there are items left in the time traveler store', function() {
|
||||
expect(scope.hasAllTimeTravelerItems()).to.eql(false);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
describe("Party Controller", function() {
|
||||
var scope, ctrl, user, User, groups, rootScope, $controller;
|
||||
var scope, ctrl, user, User, questsService, groups, rootScope, $controller;
|
||||
|
||||
beforeEach(function() {
|
||||
user = specHelper.newUser(),
|
||||
|
|
@ -15,7 +15,7 @@ describe("Party Controller", function() {
|
|||
$provide.value('User', User);
|
||||
});
|
||||
|
||||
inject(function(_$rootScope_, _$controller_, Groups){
|
||||
inject(function(_$rootScope_, _$controller_, Groups, Quests){
|
||||
|
||||
rootScope = _$rootScope_;
|
||||
|
||||
|
|
@ -24,6 +24,7 @@ describe("Party Controller", function() {
|
|||
$controller = _$controller_;
|
||||
|
||||
groups = Groups;
|
||||
questsService = Quests;
|
||||
|
||||
// Load RootCtrl to ensure shared behaviors are loaded
|
||||
$controller('RootCtrl', {$scope: scope, User: User});
|
||||
|
|
@ -33,129 +34,180 @@ describe("Party Controller", function() {
|
|||
});
|
||||
|
||||
describe('questAccept', function() {
|
||||
it('calls Groups.questAccept', function() {
|
||||
var party = {};
|
||||
var groupSpy = sandbox.stub(groups, "questAccept", function(){return true;});
|
||||
scope.questAccept(party);
|
||||
groupSpy.should.have.been.calledOnce;
|
||||
beforeEach(function() {
|
||||
scope.group = {
|
||||
quest: { members: { 'user-id': true } }
|
||||
};
|
||||
sandbox.stub(questsService, 'sendAction').returns({
|
||||
then: sandbox.stub().yields({members: {another: true}})
|
||||
});
|
||||
});
|
||||
|
||||
it('calls Quests.sendAction', function() {
|
||||
scope.questAccept();
|
||||
|
||||
expect(questsService.sendAction).to.be.calledOnce;
|
||||
expect(questsService.sendAction).to.be.calledWith('questAccept');
|
||||
});
|
||||
|
||||
|
||||
it('updates quest object with new participants list', function() {
|
||||
scope.group.quest = {
|
||||
members: { user: true, another: true }
|
||||
};
|
||||
|
||||
scope.questAccept();
|
||||
|
||||
expect(scope.group.quest).to.eql({members: { another: true }});
|
||||
});
|
||||
});
|
||||
|
||||
describe('questReject', function() {
|
||||
it('calls Groups.questReject', function() {
|
||||
var party = {};
|
||||
var groupSpy = sandbox.stub(groups, "questReject", function(){return true;});
|
||||
scope.questReject(party);
|
||||
groupSpy.should.have.been.calledOnce;
|
||||
beforeEach(function() {
|
||||
scope.group = {
|
||||
quest: { members: { 'user-id': true } }
|
||||
};
|
||||
sandbox.stub(questsService, 'sendAction').returns({
|
||||
then: sandbox.stub().yields({members: {another: true}})
|
||||
});
|
||||
});
|
||||
|
||||
it('calls Quests.sendAction', function() {
|
||||
scope.questReject();
|
||||
|
||||
expect(questsService.sendAction).to.be.calledOnce;
|
||||
expect(questsService.sendAction).to.be.calledWith('questReject');
|
||||
});
|
||||
|
||||
|
||||
it('updates quest object with new participants list', function() {
|
||||
scope.group.quest = {
|
||||
members: { user: true, another: true }
|
||||
};
|
||||
|
||||
scope.questReject();
|
||||
|
||||
expect(scope.group.quest).to.eql({members: { another: true }});
|
||||
});
|
||||
});
|
||||
|
||||
describe('questCancel', function() {
|
||||
var party, cancelSpy, windowSpy;
|
||||
beforeEach(function() {
|
||||
party = {};
|
||||
cancelSpy = sandbox.stub(groups, "questCancel", function(){return true;});
|
||||
sandbox.stub(questsService, 'sendAction').returns({
|
||||
then: sandbox.stub().yields({members: {another: true}})
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
windowSpy.restore();
|
||||
cancelSpy.restore();
|
||||
it('calls Quests.sendAction when alert box is confirmed', function() {
|
||||
sandbox.stub(window, "confirm").returns(true);
|
||||
|
||||
scope.questCancel();
|
||||
|
||||
expect(window.confirm).to.be.calledOnce;
|
||||
expect(window.confirm).to.be.calledWith(window.env.t('sureCancel'));
|
||||
expect(questsService.sendAction).to.be.calledOnce;
|
||||
expect(questsService.sendAction).to.be.calledWith('questCancel');
|
||||
});
|
||||
|
||||
it('calls Groups.questCancel when alert box is confirmed', function() {
|
||||
windowSpy = sandbox.stub(window, "confirm", function(){return true});
|
||||
it('does not call Quests.sendAction when alert box is not confirmed', function() {
|
||||
sandbox.stub(window, "confirm").returns(false);
|
||||
|
||||
scope.questCancel(party);
|
||||
windowSpy.should.have.been.calledOnce;
|
||||
windowSpy.should.have.been.calledWith(window.env.t('sureCancel'));
|
||||
cancelSpy.should.have.been.calledOnce;
|
||||
});
|
||||
scope.questCancel();
|
||||
|
||||
it('does not call Groups.questCancel when alert box is not confirmed', function() {
|
||||
windowSpy = sandbox.stub(window, "confirm", function(){return false});
|
||||
|
||||
scope.questCancel(party);
|
||||
windowSpy.should.have.been.calledOnce;
|
||||
cancelSpy.should.not.have.been.calledOnce;
|
||||
expect(window.confirm).to.be.calledOnce;
|
||||
expect(questsService.sendAction).to.not.be.called;
|
||||
});
|
||||
});
|
||||
|
||||
describe('questAbort', function() {
|
||||
var party, abortSpy, windowSpy;
|
||||
beforeEach(function() {
|
||||
party = {};
|
||||
abortSpy = sandbox.stub(groups, "questAbort", function(){return true;});
|
||||
sandbox.stub(questsService, 'sendAction').returns({
|
||||
then: sandbox.stub().yields({members: {another: true}})
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
windowSpy.restore();
|
||||
abortSpy.restore();
|
||||
it('calls Quests.sendAction when two alert boxes are confirmed', function() {
|
||||
sandbox.stub(window, "confirm", function(){return true});
|
||||
|
||||
scope.questAbort();
|
||||
expect(window.confirm).to.be.calledTwice;
|
||||
expect(window.confirm).to.be.calledWith(window.env.t('sureAbort'));
|
||||
expect(window.confirm).to.be.calledWith(window.env.t('doubleSureAbort'));
|
||||
|
||||
expect(questsService.sendAction).to.be.calledOnce;
|
||||
expect(questsService.sendAction).to.be.calledWith('questAbort');
|
||||
});
|
||||
|
||||
it('calls Groups.questAbort when two alert boxes are confirmed', function() {
|
||||
windowSpy = sandbox.stub(window, "confirm", function(){return true});
|
||||
it('does not call Quests.sendAction when first alert box is not confirmed', function() {
|
||||
sandbox.stub(window, "confirm", function(){return false});
|
||||
|
||||
scope.questAbort(party);
|
||||
windowSpy.should.have.been.calledTwice;
|
||||
windowSpy.should.have.been.calledWith(window.env.t('sureAbort'));
|
||||
windowSpy.should.have.been.calledWith(window.env.t('doubleSureAbort'));
|
||||
abortSpy.should.have.been.calledOnce;
|
||||
scope.questAbort();
|
||||
|
||||
expect(window.confirm).to.be.calledOnce;
|
||||
expect(window.confirm).to.be.calledWith(window.env.t('sureAbort'));
|
||||
expect(window.confirm).to.not.be.calledWith(window.env.t('doubleSureAbort'));
|
||||
|
||||
expect(questsService.sendAction).to.not.be.called;
|
||||
});
|
||||
|
||||
it('does not call Groups.questAbort when first alert box is not confirmed', function() {
|
||||
windowSpy = sandbox.stub(window, "confirm", function(){return false});
|
||||
|
||||
scope.questAbort(party);
|
||||
windowSpy.should.have.been.calledOnce;
|
||||
windowSpy.should.have.been.calledWith(window.env.t('sureAbort'));
|
||||
windowSpy.should.not.have.been.calledWith(window.env.t('doubleSureAbort'));
|
||||
abortSpy.should.not.have.been.calledOnce;
|
||||
});
|
||||
|
||||
it('does not call Groups.questAbort when first alert box is confirmed but second one is not', function() {
|
||||
it('does not call Quests.sendAction when first alert box is confirmed but second one is not', function() {
|
||||
// Hack to confirm first window, but not second
|
||||
// Should not be necessary when we upgrade sinon
|
||||
var shouldReturn = false;
|
||||
windowSpy = sandbox.stub(window, "confirm", function(){
|
||||
sandbox.stub(window, 'confirm', function(){
|
||||
shouldReturn = !shouldReturn;
|
||||
return shouldReturn;
|
||||
});
|
||||
|
||||
scope.questAbort(party);
|
||||
windowSpy.should.have.been.calledTwice;
|
||||
windowSpy.should.have.been.calledWith(window.env.t('sureAbort'));
|
||||
windowSpy.should.have.been.calledWith(window.env.t('doubleSureAbort'));
|
||||
abortSpy.should.not.have.been.calledOnce;
|
||||
scope.questAbort();
|
||||
|
||||
expect(window.confirm).to.be.calledTwice;
|
||||
expect(window.confirm).to.be.calledWith(window.env.t('sureAbort'));
|
||||
expect(window.confirm).to.be.calledWith(window.env.t('doubleSureAbort'));
|
||||
expect(questsService.sendAction).to.not.be.called;
|
||||
});
|
||||
});
|
||||
|
||||
describe('#questLeave', function() {
|
||||
var party, leaveSpy, windowSpy;
|
||||
|
||||
beforeEach(function() {
|
||||
party = {};
|
||||
scope.group = {
|
||||
quest: { members: { 'user-id': true } }
|
||||
};
|
||||
leaveSpy = sandbox.stub(groups, 'questLeave').returns({
|
||||
then: sandbox.stub().yields()
|
||||
sandbox.stub(questsService, 'sendAction').returns({
|
||||
then: sandbox.stub().yields({members: {another: true}})
|
||||
});
|
||||
});
|
||||
|
||||
it('calls Groups.questLeave when alert box is confirmed', function() {
|
||||
windowSpy = sandbox.stub(window, "confirm").returns(true);
|
||||
it('calls Quests.sendAction when alert box is confirmed', function() {
|
||||
sandbox.stub(window, "confirm").returns(true);
|
||||
|
||||
scope.questLeave(party);
|
||||
windowSpy.should.have.been.calledOnce;
|
||||
windowSpy.should.have.been.calledWith(window.env.t('sureLeave'));
|
||||
leaveSpy.should.have.been.calledOnce;
|
||||
scope.questLeave();
|
||||
|
||||
expect(window.confirm).to.be.calledOnce;
|
||||
expect(window.confirm).to.be.calledWith(window.env.t('sureLeave'));
|
||||
expect(questsService.sendAction).to.be.calledOnce;
|
||||
expect(questsService.sendAction).to.be.calledWith('questLeave');
|
||||
});
|
||||
|
||||
it('does not call Groups.questLeave when alert box is not confirmed', function() {
|
||||
windowSpy = sandbox.stub(window, "confirm").returns(false);
|
||||
it('does not call Quests.sendAction when alert box is not confirmed', function() {
|
||||
sandbox.stub(window, "confirm").returns(false);
|
||||
|
||||
scope.questLeave(party);
|
||||
windowSpy.should.have.been.calledOnce;
|
||||
leaveSpy.should.not.have.been.calledOnce;
|
||||
scope.questLeave();
|
||||
|
||||
expect(window.confirm).to.be.calledOnce;
|
||||
questsService.sendAction.should.not.have.been.calledOnce;
|
||||
});
|
||||
|
||||
it('updates quest object with new participants list', function() {
|
||||
scope.group.quest = {
|
||||
members: { user: true, another: true }
|
||||
};
|
||||
sandbox.stub(window, "confirm").returns(true);
|
||||
|
||||
scope.questLeave();
|
||||
|
||||
expect(scope.group.quest).to.eql({members: { another: true }});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -241,4 +293,28 @@ describe("Party Controller", function() {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#canEditQuest', function() {
|
||||
var party;
|
||||
|
||||
beforeEach(function() {
|
||||
party = specHelper.newGroup({
|
||||
type: 'party',
|
||||
leader: {},
|
||||
quest: {}
|
||||
});
|
||||
});
|
||||
|
||||
it('returns false if user is not the quest leader', function() {
|
||||
party.quest.leader = 'another-user';
|
||||
|
||||
expect(scope.canEditQuest(party)).to.eql(false);
|
||||
});
|
||||
|
||||
it('returns true if user is quest leader', function() {
|
||||
party.quest.leader = 'unique-user-id';
|
||||
|
||||
expect(scope.canEditQuest(party)).to.eql(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -39,67 +39,4 @@ describe('groupServices', function() {
|
|||
groups.myGuilds();
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
context('quest function wrappers', function() {
|
||||
var successPromise, failPromise;
|
||||
|
||||
beforeEach(function() {
|
||||
sandbox.spy(user, 'sync');
|
||||
sandbox.stub(console, 'log');
|
||||
|
||||
successPromise = sandbox.stub().returns({
|
||||
then: function(success, failure) {
|
||||
return success();
|
||||
}
|
||||
});
|
||||
|
||||
failPromise = sandbox.stub().returns({
|
||||
then: function(success, failure) {
|
||||
return failure('fail');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var questFunctions = [
|
||||
'questAccept',
|
||||
'questReject',
|
||||
'questCancel',
|
||||
'questAbort',
|
||||
'questLeave'
|
||||
];
|
||||
|
||||
for (var i in questFunctions) {
|
||||
var questFunc = questFunctions[i];
|
||||
|
||||
describe('#' + questFunc, function() {
|
||||
it('calls party.$' + questFunc, function() {
|
||||
var party = { };
|
||||
party['$' + questFunc] = successPromise;
|
||||
|
||||
groups[questFunc](party);
|
||||
|
||||
expect(party['$' + questFunc]).to.be.calledOnce;
|
||||
});
|
||||
|
||||
it('syncs user if $' + questFunc + ' succeeds', function() {
|
||||
var successParty = { };
|
||||
successParty['$' + questFunc] = successPromise;
|
||||
|
||||
groups[questFunc](successParty);
|
||||
|
||||
user.sync.should.have.been.calledOnce;
|
||||
});
|
||||
|
||||
it('does not sync user if $' + questFunc + ' fails', function() {
|
||||
var failParty = { };
|
||||
failParty['$' + questFunc] = failPromise;
|
||||
|
||||
groups[questFunc](failParty);
|
||||
|
||||
user.sync.should.not.have.been.calledOnce;
|
||||
console.log.should.have.been.calledWith('fail');
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
describe('Quests Service', function() {
|
||||
var scope, rootScope, groupsService, quest, questsService, user, content;
|
||||
var groupsService, quest, questsService, user, content, resolveSpy, rejectSpy;
|
||||
|
||||
beforeEach(function() {
|
||||
user = specHelper.newUser();
|
||||
|
|
@ -13,108 +13,378 @@ describe('Quests Service', function() {
|
|||
quest = {lvl:20};
|
||||
|
||||
module(function($provide) {
|
||||
$provide.value('User', {user: user});
|
||||
$provide.value('User', {sync: sinon.stub(), user: user});
|
||||
});
|
||||
|
||||
inject(function($rootScope, $controller, Quests, Groups, Content) {
|
||||
scope = $rootScope.$new();
|
||||
rootScope = $rootScope;
|
||||
$controller('RootCtrl', {$scope: scope, User: {user: user}});
|
||||
inject(function(Quests, Groups, Content) {
|
||||
questsService = Quests;
|
||||
groupsService = Groups;
|
||||
content = Content;
|
||||
});
|
||||
|
||||
sandbox.stub(groupsService, 'inviteOrStartParty');
|
||||
sandbox.stub(rootScope, 'openModal');
|
||||
sandbox.stub(window,'confirm',function(){return true});
|
||||
sandbox.stub(window,'confirm');
|
||||
sandbox.stub(window,'alert');
|
||||
resolveSpy = sandbox.spy();
|
||||
rejectSpy = sandbox.spy();
|
||||
});
|
||||
|
||||
context('functions', function() {
|
||||
describe('#lockQuest', function() {
|
||||
|
||||
describe('lock quest', function() {
|
||||
it('locks quest when user does not meet level requirement', function() {
|
||||
user.stats.lvl = 15;
|
||||
|
||||
it('locks quest when user does not meet level requirement', function() {
|
||||
user.stats.lvl = 15;
|
||||
expect(questsService.lockQuest(quest)).to.be.ok;
|
||||
});
|
||||
|
||||
expect(questsService.lockQuest(quest)).to.be.ok;
|
||||
});
|
||||
it('does not lock quest if we ignore level requirement', function() {
|
||||
user.stats.lvl = 15;
|
||||
|
||||
it('does not lock quest if we ignore level requirement', function() {
|
||||
user.stats.lvl = 15;
|
||||
expect(questsService.lockQuest(quest,true)).to.not.be.ok;
|
||||
});
|
||||
|
||||
expect(questsService.lockQuest(quest,true)).to.not.be.ok;
|
||||
});
|
||||
it('does not lock quest if user meets level requirement', function() {
|
||||
user.stats.lvl = 20;
|
||||
|
||||
it('does not lock quest if user meets level requirement', function() {
|
||||
user.stats.lvl = 20;
|
||||
expect(questsService.lockQuest(quest)).to.not.be.ok;
|
||||
});
|
||||
|
||||
expect(questsService.lockQuest(quest)).to.not.be.ok;
|
||||
});
|
||||
it('locks quest if user has not completed previous quest in series', function() {
|
||||
quest.previous = 'priorQuest';
|
||||
user.stats.lvl = 25;
|
||||
|
||||
it('locks quest if user has not completed previous quest in series', function() {
|
||||
quest.previous = 'priorQuest';
|
||||
user.stats.lvl = 25;
|
||||
expect(questsService.lockQuest(quest)).to.be.ok;
|
||||
});
|
||||
|
||||
expect(questsService.lockQuest(quest)).to.be.ok;
|
||||
});
|
||||
it('does not lock quest if user has completed previous quest in series', function() {
|
||||
quest.previous = 'priorQuest';
|
||||
user.stats.lvl = 25;
|
||||
user.achievements.quests.priorQuest = 1;
|
||||
|
||||
it('does not lock quest if user has completed previous quest in series', function() {
|
||||
quest.previous = 'priorQuest';
|
||||
user.stats.lvl = 25;
|
||||
user.achievements.quests.priorQuest = 1;
|
||||
expect(questsService.lockQuest(quest)).to.not.be.ok;
|
||||
});
|
||||
});
|
||||
|
||||
expect(questsService.lockQuest(quest)).to.not.be.ok;
|
||||
describe('#buyQuest', function() {
|
||||
var scope;
|
||||
|
||||
beforeEach(inject(function($rootScope) {
|
||||
scope = $rootScope.$new();
|
||||
}));
|
||||
|
||||
it('returns a promise', function() {
|
||||
var promise = questsService.buyQuest('whale');
|
||||
expect(promise).to.respondTo('then');
|
||||
});
|
||||
|
||||
context('Quest key does not exist', function() {
|
||||
it('rejects with message that quest is not found', function(done) {
|
||||
questsService.buyQuest('foo')
|
||||
.then(resolveSpy, function(rej) {
|
||||
expect(rej).to.eql('No quest with that key found');
|
||||
expect(resolveSpy).to.not.be.called;
|
||||
done();
|
||||
});
|
||||
|
||||
scope.$apply();
|
||||
});
|
||||
});
|
||||
|
||||
describe('buy quest', function() {
|
||||
|
||||
context('invite friends', function() {
|
||||
it('prompts user to invite friends to party for invite reward quests', function() {
|
||||
questsService.buyQuest('basilist');
|
||||
|
||||
expect(window.confirm).to.have.been.calledOnce;
|
||||
expect(groupsService.inviteOrStartParty).to.have.been.calledOnce;
|
||||
expect(rootScope.openModal).to.have.been.notCalled;
|
||||
expect(window.confirm).to.be.calledOnce;
|
||||
expect(window.confirm).to.be.calledWith(env.t('mustInviteFriend'));
|
||||
});
|
||||
|
||||
it('does not allow user to buy quests whose previous quests are incomplete', function() {
|
||||
it('rejects promise if confirm is cancelled', function(done) {
|
||||
window.confirm.returns(false);
|
||||
|
||||
questsService.buyQuest('basilist')
|
||||
.then(resolveSpy, function(rej) {
|
||||
expect(rej).to.eql('Did not want to invite friends');
|
||||
expect(window.confirm).to.be.calledOnce;
|
||||
expect(groupsService.inviteOrStartParty).to.not.be.called;
|
||||
done();
|
||||
});
|
||||
|
||||
scope.$apply();
|
||||
});
|
||||
|
||||
it('rejects promise if confirm is cofirmed and calls groups service', function(done) {
|
||||
window.confirm.returns(true);
|
||||
|
||||
questsService.buyQuest('basilist')
|
||||
.then(resolveSpy, function(rej) {
|
||||
expect(rej).to.eql('Invite or start party');
|
||||
expect(window.confirm).to.be.calledOnce;
|
||||
expect(groupsService.inviteOrStartParty).to.be.calledOnce;
|
||||
done();
|
||||
});
|
||||
|
||||
scope.$apply();
|
||||
});
|
||||
});
|
||||
|
||||
context('quests in a series', function() {
|
||||
it('does not allow user to buy subsquent quests in a series if user has no quest achievements', function(done) {
|
||||
user.stats.lvl = 100;
|
||||
user.achievements.quests = undefined;
|
||||
|
||||
questsService.buyQuest('goldenknight2');
|
||||
questsService.buyQuest('goldenknight2')
|
||||
.then(resolveSpy, function(res) {
|
||||
expect(window.alert).to.have.been.calledOnce;
|
||||
expect(res).to.eql('unlockByQuesting');
|
||||
expect(resolveSpy).to.not.be.called;
|
||||
done();
|
||||
});
|
||||
|
||||
expect(window.alert).to.have.been.calledOnce;
|
||||
expect(rootScope.openModal).to.have.been.notCalled;
|
||||
scope.$apply();
|
||||
});
|
||||
|
||||
it('does not allow user to buy quests beyond their level', function() {
|
||||
it('does not allow user to buy quests whose previous quests are incomplete', function(done) {
|
||||
user.stats.lvl = 100;
|
||||
user.achievements.quests = {
|
||||
'atom1': 1
|
||||
};
|
||||
|
||||
questsService.buyQuest('goldenknight2')
|
||||
.then(resolveSpy, function(res) {
|
||||
expect(window.alert).to.have.been.calledOnce;
|
||||
expect(resolveSpy).to.not.be.called;
|
||||
done();
|
||||
});
|
||||
|
||||
scope.$apply();
|
||||
});
|
||||
});
|
||||
|
||||
context('quests with level requirement', function() {
|
||||
it('does not allow user to buy quests beyond their level', function(done) {
|
||||
user.stats.lvl = 1;
|
||||
|
||||
questsService.buyQuest('vice1');
|
||||
questsService.buyQuest('vice1')
|
||||
.then(resolveSpy, function(res) {
|
||||
expect(window.alert).to.have.been.calledOnce;
|
||||
expect(res).to.eql('mustLvlQuest');
|
||||
done();
|
||||
});
|
||||
|
||||
expect(window.alert).to.have.been.calledOnce;
|
||||
expect(rootScope.openModal).to.have.been.notCalled;
|
||||
scope.$apply();
|
||||
});
|
||||
|
||||
it('opens purchase modal if Gem quest prerequisites are met', function() {
|
||||
user.stats.lvl = 100;
|
||||
user.achievements.quests.atom1 = 2;
|
||||
it('allows user to buy quest if they meet level requirement', function(done) {
|
||||
user.stats.lvl = 30;
|
||||
|
||||
questsService.buyQuest('atom2');
|
||||
questsService.buyQuest('vice1')
|
||||
.then(function(res) {
|
||||
expect(res).to.eql(content.quests.vice1);
|
||||
expect(window.alert).to.not.be.called;
|
||||
expect(rejectSpy).to.not.be.called;
|
||||
done();
|
||||
}, rejectSpy);
|
||||
|
||||
expect(scope.selectedQuest).to.eql(content.quests.atom2);
|
||||
expect(rootScope.openModal).to.have.been.calledOnce;
|
||||
expect(rootScope.openModal).to.have.been.calledWith('buyQuest');
|
||||
scope.$apply();
|
||||
});
|
||||
});
|
||||
|
||||
it('opens purchase modal if quest is Gold-purchasable', function() {
|
||||
questsService.buyQuest('dilatoryDistress1');
|
||||
context('gold purchasable quests', function() {
|
||||
it('sends quest object', function(done) {
|
||||
questsService.buyQuest('dilatoryDistress1')
|
||||
.then(function(res) {
|
||||
expect(res).to.eql(content.quests.dilatoryDistress1);
|
||||
expect(window.alert).to.not.be.called;
|
||||
expect(rejectSpy).to.not.be.called;
|
||||
done();
|
||||
}, rejectSpy);
|
||||
|
||||
expect(scope.selectedQuest).to.eql(content.quests.dilatoryDistress1);
|
||||
expect(rootScope.openModal).to.have.been.calledOnce;
|
||||
expect(rootScope.openModal).to.have.been.calledWith('buyQuest');
|
||||
scope.$apply();
|
||||
});
|
||||
});
|
||||
|
||||
context('all other quests', function() {
|
||||
it('sends quest object', function(done) {
|
||||
questsService.buyQuest('whale')
|
||||
.then(function(res) {
|
||||
expect(res).to.eql(content.quests.whale);
|
||||
expect(window.alert).to.not.be.called;
|
||||
expect(rejectSpy).to.not.be.called;
|
||||
done();
|
||||
}, rejectSpy);
|
||||
|
||||
scope.$apply();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#showQuest', function() {
|
||||
var scope;
|
||||
|
||||
beforeEach(inject(function($rootScope) {
|
||||
scope = $rootScope.$new();
|
||||
}));
|
||||
|
||||
it('returns a promise', function() {
|
||||
var promise = questsService.showQuest('whale');
|
||||
expect(promise).to.respondTo('then');
|
||||
});
|
||||
|
||||
context('Quest key does not exist', function() {
|
||||
it('rejects with message that quest is not found', function(done) {
|
||||
questsService.showQuest('foo')
|
||||
.then(resolveSpy, function(rej) {
|
||||
expect(rej).to.eql('No quest with that key found');
|
||||
expect(resolveSpy).to.not.be.called;
|
||||
done();
|
||||
});
|
||||
|
||||
scope.$apply();
|
||||
});
|
||||
});
|
||||
|
||||
context('quests in a series', function() {
|
||||
it('does not allow user to buy subsquent quests in a series if user has no quest achievements', function(done) {
|
||||
user.stats.lvl = 100;
|
||||
user.achievements.quests = undefined;
|
||||
|
||||
questsService.showQuest('goldenknight2')
|
||||
.then(resolveSpy, function(res) {
|
||||
expect(window.alert).to.have.been.calledOnce;
|
||||
expect(res).to.eql('unlockByQuesting');
|
||||
expect(resolveSpy).to.not.be.called;
|
||||
done();
|
||||
});
|
||||
|
||||
scope.$apply();
|
||||
});
|
||||
|
||||
it('does not allow user to buy quests whose previous quests are incomplete', function(done) {
|
||||
user.stats.lvl = 100;
|
||||
user.achievements.quests = {
|
||||
'atom1': 1
|
||||
};
|
||||
|
||||
questsService.showQuest('goldenknight2')
|
||||
.then(resolveSpy, function(res) {
|
||||
expect(window.alert).to.have.been.calledOnce;
|
||||
expect(resolveSpy).to.not.be.called;
|
||||
done();
|
||||
});
|
||||
|
||||
scope.$apply();
|
||||
});
|
||||
});
|
||||
|
||||
context('quests with level requirement', function() {
|
||||
it('does not allow user to buy quests beyond their level', function(done) {
|
||||
user.stats.lvl = 1;
|
||||
|
||||
questsService.showQuest('vice1')
|
||||
.then(resolveSpy, function(res) {
|
||||
expect(window.alert).to.have.been.calledOnce;
|
||||
expect(res).to.eql('mustLvlQuest');
|
||||
done();
|
||||
});
|
||||
|
||||
scope.$apply();
|
||||
});
|
||||
|
||||
it('allows user to buy quest if they meet level requirement', function(done) {
|
||||
user.stats.lvl = 30;
|
||||
|
||||
questsService.showQuest('vice1')
|
||||
.then(function(res) {
|
||||
expect(res).to.eql(content.quests.vice1);
|
||||
expect(window.alert).to.not.be.called;
|
||||
expect(rejectSpy).to.not.be.called;
|
||||
done();
|
||||
}, rejectSpy);
|
||||
|
||||
scope.$apply();
|
||||
});
|
||||
});
|
||||
|
||||
context('gold purchasable quests', function() {
|
||||
it('sends quest object', function(done) {
|
||||
questsService.showQuest('dilatoryDistress1')
|
||||
.then(function(res) {
|
||||
expect(res).to.eql(content.quests.dilatoryDistress1);
|
||||
expect(window.alert).to.not.be.called;
|
||||
expect(rejectSpy).to.not.be.called;
|
||||
done();
|
||||
}, rejectSpy);
|
||||
|
||||
scope.$apply();
|
||||
});
|
||||
});
|
||||
|
||||
context('all other quests', function() {
|
||||
it('sends quest object', function(done) {
|
||||
questsService.showQuest('whale')
|
||||
.then(function(res) {
|
||||
expect(res).to.eql(content.quests.whale);
|
||||
expect(window.alert).to.not.be.called;
|
||||
expect(rejectSpy).to.not.be.called;
|
||||
done();
|
||||
}, rejectSpy);
|
||||
|
||||
scope.$apply();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#initQuest', function() {
|
||||
|
||||
it('returns a promise', function() {
|
||||
var promise = questsService.initQuest('whale');
|
||||
expect(promise).to.respondTo('then');
|
||||
});
|
||||
|
||||
it('accepts quest');
|
||||
|
||||
it('brings user to party page');
|
||||
});
|
||||
|
||||
describe('#sendAction', function() {
|
||||
var fakeBackend, scope;
|
||||
|
||||
beforeEach(inject(function($httpBackend, $rootScope) {
|
||||
scope = $rootScope.$new();
|
||||
fakeBackend = $httpBackend;
|
||||
|
||||
fakeBackend.when('GET', 'partials/main.html').respond({});
|
||||
fakeBackend.when('GET', '/api/v2/groups/party').respond({_id: 'party-id'});
|
||||
fakeBackend.when('POST', '/api/v2/groups/party-id/questReject').respond({quest: { key: 'whale' } });
|
||||
fakeBackend.flush();
|
||||
}));
|
||||
|
||||
it('returns a promise', function() {
|
||||
var promise = questsService.sendAction('questReject');
|
||||
expect(promise).to.respondTo('then');
|
||||
});
|
||||
|
||||
it('calls specified quest endpoint', function(done) {
|
||||
fakeBackend.expectPOST('/api/v2/groups/party-id/questReject');
|
||||
|
||||
questsService.sendAction('questReject')
|
||||
.then(function(res) {
|
||||
expect(res.key).to.eql('whale');
|
||||
done();
|
||||
});
|
||||
|
||||
fakeBackend.flush();
|
||||
scope.$apply();
|
||||
});
|
||||
|
||||
it('syncs User', function() {
|
||||
questsService.sendAction('questReject')
|
||||
.then(function(res) {
|
||||
expect(User.sync).to.be.calledOnce;
|
||||
done();
|
||||
});
|
||||
|
||||
scope.$apply();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -13,11 +13,33 @@ habitrpg.controller("InventoryCtrl",
|
|||
|
||||
// Functions from Quests service
|
||||
$scope.lockQuest = Quests.lockQuest;
|
||||
$scope.buyQuest = Quests.buyQuest;
|
||||
|
||||
$scope.buyQuest = function(questScroll) {
|
||||
Quests.buyQuest(questScroll)
|
||||
.then(function(quest) {
|
||||
$rootScope.selectedQuest = quest;
|
||||
$rootScope.openModal('buyQuest', {controller:'InventoryCtrl'});
|
||||
});
|
||||
};
|
||||
|
||||
$scope.questPopover = Quests.questPopover;
|
||||
$scope.showQuest = Quests.showQuest;
|
||||
$scope.closeQuest = Quests.closeQuest;
|
||||
$scope.questInit = Quests.questInit;
|
||||
|
||||
$scope.showQuest = function(questScroll) {
|
||||
Quests.showQuest(questScroll)
|
||||
.then(function(quest) {
|
||||
$rootScope.selectedQuest = quest;
|
||||
$rootScope.openModal('showQuest', {controller:'InventoryCtrl'});
|
||||
});
|
||||
};
|
||||
|
||||
$scope.questInit = function() {
|
||||
var key = $rootScope.selectedQuest.key;
|
||||
|
||||
Quests.initQuest(key).then(function() {
|
||||
$rootScope.selectedQuest = undefined;
|
||||
$scope.$close();
|
||||
});
|
||||
};
|
||||
|
||||
// count egg, food, hatchingPotion stack totals
|
||||
var countStacks = function(items) { return _.reduce(items,function(m,v){return m+v;},0);}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ habitrpg.controller("PartyCtrl", ['$rootScope','$scope','Groups','Chat','User','
|
|||
$scope.group = $rootScope.party = Groups.party();
|
||||
$scope.newGroup = new Groups.Group({type:'party'});
|
||||
$scope.inviteOrStartParty = Groups.inviteOrStartParty;
|
||||
$scope.questInit = Quests.questInit;
|
||||
|
||||
if ($state.is('options.social.party')) {
|
||||
$scope.group.$syncParty(); // Sync party automatically when navigating to party page
|
||||
|
|
@ -105,30 +104,52 @@ habitrpg.controller("PartyCtrl", ['$rootScope','$scope','Groups','Chat','User','
|
|||
User.set({'invitations.party':{}});
|
||||
}
|
||||
|
||||
$scope.questCancel = function(party){
|
||||
$scope.questCancel = function(){
|
||||
if (!confirm(window.env.t('sureCancel'))) return;
|
||||
Groups.questCancel(party);
|
||||
|
||||
Quests.sendAction('questCancel')
|
||||
.then(function(quest) {
|
||||
$scope.group.quest = quest;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.questAbort = function(party){
|
||||
$scope.questAbort = function(){
|
||||
if (!confirm(window.env.t('sureAbort'))) return;
|
||||
if (!confirm(window.env.t('doubleSureAbort'))) return;
|
||||
Groups.questAbort(party);
|
||||
|
||||
Quests.sendAction('questAbort')
|
||||
.then(function(quest) {
|
||||
$scope.group.quest = quest;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.questLeave = function(party){
|
||||
$scope.questLeave = function(){
|
||||
if (!confirm(window.env.t('sureLeave'))) return;
|
||||
|
||||
delete $scope.group.quest.members[User.user._id];
|
||||
Groups.questLeave(party);
|
||||
Quests.sendAction('questLeave')
|
||||
.then(function(quest) {
|
||||
$scope.group.quest = quest;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.questAccept = function(party){
|
||||
Groups.questAccept(party);
|
||||
$scope.questAccept = function(){
|
||||
Quests.sendAction('questAccept')
|
||||
.then(function(quest) {
|
||||
$scope.group.quest = quest;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.questReject = function(party){
|
||||
Groups.questReject(party);
|
||||
}
|
||||
$scope.questReject = function(){
|
||||
Quests.sendAction('questReject')
|
||||
.then(function(quest) {
|
||||
$scope.group.quest = quest;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.canEditQuest = function(party) {
|
||||
var isQuestLeader = party.quest && party.quest.leader === User.user._id;
|
||||
|
||||
return isQuestLeader;
|
||||
};
|
||||
}
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -39,21 +39,9 @@
|
|||
leave: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/leave'},
|
||||
invite: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/invite'},
|
||||
removeMember: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/removeMember'},
|
||||
questAccept: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/questAccept'},
|
||||
questReject: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/questReject'},
|
||||
questCancel: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/questCancel'},
|
||||
questAbort: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/questAbort'},
|
||||
questLeave: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/questLeave'}
|
||||
startQuest: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/questAccept'}
|
||||
});
|
||||
|
||||
function _syncUser() {
|
||||
User.sync();
|
||||
}
|
||||
|
||||
function _logError(err) {
|
||||
console.log(err);
|
||||
}
|
||||
|
||||
function party(cb) {
|
||||
if (!data.party) return (data.party = Group.get({gid: 'party'}, cb));
|
||||
return (cb) ? cb(party) : data.party;
|
||||
|
|
@ -75,36 +63,6 @@
|
|||
return data.tavern;
|
||||
}
|
||||
|
||||
function questAccept(party) {
|
||||
Analytics.updateUser({'partyID':party.id,'partySize':party.memberCount});
|
||||
return party.$questAccept()
|
||||
.then(_syncUser, _logError);
|
||||
}
|
||||
|
||||
function questReject(party) {
|
||||
Analytics.updateUser({'partyID':party.id,'partySize':party.memberCount});
|
||||
return party.$questReject()
|
||||
.then(_syncUser, _logError);
|
||||
}
|
||||
|
||||
function questCancel(party) {
|
||||
Analytics.updateUser({'partyID':party.id,'partySize':party.memberCount});
|
||||
return party.$questCancel()
|
||||
.then(_syncUser, _logError);
|
||||
}
|
||||
|
||||
function questAbort(party) {
|
||||
Analytics.updateUser({'partyID':party.id,'partySize':party.memberCount});
|
||||
return party.$questAbort()
|
||||
.then(_syncUser, _logError);
|
||||
}
|
||||
|
||||
function questLeave(party) {
|
||||
Analytics.updateUser({'partyID':party.id,'partySize':party.memberCount});
|
||||
return party.$questLeave()
|
||||
.then(_syncUser, _logError);
|
||||
}
|
||||
|
||||
function inviteOrStartParty(group) {
|
||||
Analytics.track({'hitType':'event','eventCategory':'button','eventAction':'click','eventLabel':'Invite Friends'});
|
||||
if (group.type === "party" || $location.$$path === "/options/groups/party") {
|
||||
|
|
@ -125,11 +83,6 @@
|
|||
publicGuilds: publicGuilds,
|
||||
myGuilds: myGuilds,
|
||||
tavern: tavern,
|
||||
questAccept: questAccept,
|
||||
questReject: questReject,
|
||||
questAbort: questAbort,
|
||||
questLeave: questLeave,
|
||||
questCancel: questCancel,
|
||||
inviteOrStartParty: inviteOrStartParty,
|
||||
|
||||
data: data,
|
||||
|
|
|
|||
|
|
@ -6,14 +6,17 @@
|
|||
.factory('Quests', questsFactory);
|
||||
|
||||
questsFactory.$inject = [
|
||||
'$rootScope',
|
||||
'$http',
|
||||
'$state',
|
||||
'$q',
|
||||
'ApiUrl',
|
||||
'Content',
|
||||
'Groups',
|
||||
'User',
|
||||
'Analytics'
|
||||
];
|
||||
|
||||
function questsFactory($rootScope,Content,Groups,User,Analytics) {
|
||||
function questsFactory($http, $state, $q, ApiUrl, Content, Groups, User, Analytics) {
|
||||
|
||||
var user = User.user;
|
||||
var party = Groups.party();
|
||||
|
|
@ -26,21 +29,39 @@
|
|||
return (quest.previous);
|
||||
}
|
||||
|
||||
function buyQuest(quest) {
|
||||
var item = Content.quests[quest];
|
||||
function _preventQuestModal(quest) {
|
||||
if (!quest) {
|
||||
return 'No quest with that key found';
|
||||
}
|
||||
|
||||
if (item.unlockCondition && item.unlockCondition.condition === 'party invite') {
|
||||
if (!confirm(window.env.t('mustInviteFriend'))) return;
|
||||
return Groups.inviteOrStartParty(party);
|
||||
if (quest.previous && (!user.achievements.quests || (user.achievements.quests && !user.achievements.quests[quest.previous]))){
|
||||
alert(window.env.t('unlockByQuesting', {title: Content.quests[quest.previous].text()}));
|
||||
return 'unlockByQuesting';
|
||||
}
|
||||
if (item.previous && (!User.user.achievements.quests || (User.user.achievements.quests && !User.user.achievements.quests[item.previous]))){
|
||||
return alert(window.env.t('unlockByQuesting', {title: Content.quests[item.previous].text()}));
|
||||
|
||||
if (quest.lvl > user.stats.lvl) {
|
||||
alert(window.env.t('mustLvlQuest', {level: quest.lvl}))
|
||||
return 'mustLvlQuest';
|
||||
}
|
||||
if (item.lvl && item.lvl > user.stats.lvl) {
|
||||
return alert(window.env.t('mustLvlQuest', {level: item.lvl}));
|
||||
}
|
||||
$rootScope.selectedQuest = item;
|
||||
$rootScope.openModal('buyQuest', {controller:'InventoryCtrl'});
|
||||
}
|
||||
|
||||
function buyQuest(quest) {
|
||||
return $q(function(resolve, reject) {
|
||||
var item = Content.quests[quest];
|
||||
|
||||
var preventQuestModal = _preventQuestModal(item);
|
||||
if (preventQuestModal) {
|
||||
return reject(preventQuestModal);
|
||||
}
|
||||
|
||||
if (item.unlockCondition && item.unlockCondition.condition === 'party invite') {
|
||||
if (!confirm(window.env.t('mustInviteFriend'))) return reject('Did not want to invite friends');
|
||||
Groups.inviteOrStartParty(party)
|
||||
return reject('Invite or start party');
|
||||
}
|
||||
|
||||
resolve(item);
|
||||
});
|
||||
}
|
||||
|
||||
function questPopover(quest) {
|
||||
|
|
@ -71,37 +92,55 @@
|
|||
}
|
||||
|
||||
function showQuest(quest) {
|
||||
var item = Content.quests[quest];
|
||||
var completedPrevious = !item.previous || (User.user.achievements.quests && User.user.achievements.quests[item.previous]);
|
||||
if (!completedPrevious)
|
||||
return alert(window.env.t('mustComplete', {quest: $rootScope.Content.quests[item.previous].text()}));
|
||||
if (item.lvl && item.lvl > user.stats.lvl)
|
||||
return alert(window.env.t('mustLevel', {level: item.lvl}));
|
||||
$rootScope.selectedQuest = item;
|
||||
$rootScope.openModal('showQuest', {controller:'InventoryCtrl'});
|
||||
}
|
||||
return $q(function(resolve, reject) {
|
||||
var item = Content.quests[quest];
|
||||
|
||||
function closeQuest(){
|
||||
$rootScope.selectedQuest = undefined;
|
||||
}
|
||||
var preventQuestModal = _preventQuestModal(item);
|
||||
if (preventQuestModal) {
|
||||
return reject(preventQuestModal);
|
||||
}
|
||||
|
||||
function questInit(){
|
||||
Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'quest','owner':true,'response':'accept','questName':$rootScope.selectedQuest.key});
|
||||
Analytics.updateUser({'partyID':party._id,'partySize':party.memberCount});
|
||||
party.$questAccept({key:$rootScope.selectedQuest.key}, function(){
|
||||
party.$get();
|
||||
$rootScope.$state.go('options.social.party');
|
||||
resolve(item);
|
||||
});
|
||||
}
|
||||
|
||||
function initQuest(key) {
|
||||
return $q(function(resolve, reject) {
|
||||
Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'quest','owner':true,'response':'accept','questName': key});
|
||||
Analytics.updateUser({'partyID':party._id,'partySize':party.memberCount});
|
||||
party.$startQuest({key:key}, function(){
|
||||
party.$syncParty();
|
||||
$state.go('options.social.party');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function sendAction(action) {
|
||||
return $q(function(resolve, reject) {
|
||||
|
||||
$http.post(ApiUrl.get() + '/api/v2/groups/' + party._id + '/' + action)
|
||||
.then(function(response) {
|
||||
User.sync();
|
||||
|
||||
Analytics.updateUser({
|
||||
partyID: party._id,
|
||||
partySize: party.memberCount
|
||||
});
|
||||
|
||||
var quest = response.data.quest;
|
||||
resolve(quest);
|
||||
});;
|
||||
});
|
||||
closeQuest();
|
||||
}
|
||||
|
||||
return {
|
||||
lockQuest: lockQuest,
|
||||
buyQuest: buyQuest,
|
||||
questPopover: questPopover,
|
||||
sendAction: sendAction,
|
||||
showQuest: showQuest,
|
||||
closeQuest: closeQuest,
|
||||
questInit: questInit
|
||||
initQuest: initQuest
|
||||
}
|
||||
}
|
||||
}());
|
||||
|
|
|
|||
|
|
@ -505,8 +505,14 @@ api.leave = function(req, res, next) {
|
|||
var user = res.locals.user;
|
||||
var group = res.locals.group;
|
||||
|
||||
if (group.type === 'party' && user.party.quest && user.party.quest.key) {
|
||||
return res.json(403, 'You cannot leave party during an active quest. Please leave the quest first');
|
||||
if (group.type === 'party') {
|
||||
if (group.quest && group.quest.leader === user._id) {
|
||||
return res.json(403, 'You cannot leave your party when you have started a quest. Abort the quest first.');
|
||||
}
|
||||
|
||||
if (group.quest && group.quest.active && group.quest.members && group.quest.members[user._id]) {
|
||||
return res.json(403, 'You cannot leave party during an active quest. Please leave the quest first');
|
||||
}
|
||||
}
|
||||
|
||||
// When removing the user from challenges, should we keep the tasks?
|
||||
|
|
@ -709,11 +715,14 @@ api.removeMember = function(req, res, next){
|
|||
|
||||
if(_.contains(group.members, uuid)){
|
||||
var update = {$pull:{members:uuid}};
|
||||
if(group.quest && group.quest.members){
|
||||
if (group.quest && group.quest.leader === uuid) {
|
||||
update['$set'] = {
|
||||
quest: { key: null, leader: null }
|
||||
};
|
||||
} else if(group.quest && group.quest.members){
|
||||
// remove member from quest
|
||||
update['$unset'] = {};
|
||||
update['$unset']['quest.members.' + uuid] = "";
|
||||
// TODO: run cleanQuestProgress and return scroll to member if member was quest owner
|
||||
}
|
||||
update['$inc'] = {memberCount: -1};
|
||||
Group.update({_id:group._id},update, function(err, saved){
|
||||
|
|
@ -727,6 +736,10 @@ api.removeMember = function(req, res, next){
|
|||
//Mark removed users messages as seen
|
||||
var update = {$unset:{}};
|
||||
update.$unset['newMessages.' + group._id] = '';
|
||||
if (group.quest && group.quest.active && group.quest.leader === uuid) {
|
||||
update['$inc'] = {};
|
||||
update['$inc']['items.quests.' + group.quest.key] = 1;
|
||||
}
|
||||
User.update({_id: removedUser._id, apiToken: removedUser.apiToken}, update).exec();
|
||||
|
||||
// Sending an empty 204 because Group.update doesn't return the group
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
div(ng-if='group.quest.active==true')
|
||||
div(ng-if='group.quest.active===true')
|
||||
unless tavern
|
||||
tabset
|
||||
tab(heading=env.t('questDetails'))
|
||||
|
|
@ -20,7 +20,7 @@ div(ng-if='group.quest.active==true')
|
|||
include ./ianQuestInfo
|
||||
|
||||
unless tavern
|
||||
button.btn.btn-sm.btn-warning(ng-if=':: (group.quest.leader && group.quest.leader==user._id && isMemberOfRunningQuest(group.quest.leader,group))',
|
||||
ng-click='questAbort(party)')=env.t('abort')
|
||||
button.btn.btn-sm.btn-warning(ng-if='::canEditQuest(party)',
|
||||
ng-click='questAbort()')=env.t('abort')
|
||||
button.btn.btn-sm.btn-warning(ng-if='!(group.quest.leader && group.quest.leader === user._id) && isMemberOfRunningQuest(user._id,group)',
|
||||
ng-click='questLeave(party)')=env.t('leaveQuest')
|
||||
ng-click='questLeave()')=env.t('leaveQuest')
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
div(ng-if='group.quest.active==false')
|
||||
div(ng-if='group.quest.active===false')
|
||||
tabset
|
||||
tab(heading=env.t('invitations'))
|
||||
+participants(false)
|
||||
|
|
@ -22,9 +22,9 @@ div(ng-if='group.quest.active==false')
|
|||
p=env.t('questStart')
|
||||
|
||||
span(ng-if='user.party.quest.RSVPNeeded')
|
||||
button.btn.btn-sm.btn-success(ng-click='questAccept(party)')=env.t('accept')
|
||||
button.btn.btn-sm.btn-danger(ng-click='questReject(party)')=env.t('reject')
|
||||
button.btn.btn-sm.btn-success(ng-click='questAccept()')=env.t('accept')
|
||||
button.btn.btn-sm.btn-danger(ng-click='questReject()')=env.t('reject')
|
||||
|
||||
span(ng-if='::group.quest.leader && group.quest.leader==user._id && isMemberOfGroup(group.quest.leader,group) && isMemberOfPendingQuest(group.quest.leader,group)')
|
||||
button.btn.btn-sm.btn-warning(ng-click='party.$questAccept({"force":true})')=env.t('begin')
|
||||
button.btn.btn-sm.btn-danger(ng-click='questCancel(party)')=env.t('cancel')
|
||||
span(ng-if='::canEditQuest(party)')
|
||||
button.btn.btn-sm.btn-warning(ng-click='party.$startQuest({"force":true})')=env.t('begin')
|
||||
button.btn.btn-sm.btn-danger(ng-click='questCancel()')=env.t('cancel')
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ script(type='text/ng-template', id='modals/showQuest.html')
|
|||
p=env.t('questWarning')
|
||||
.modal-footer
|
||||
button.btn.btn-default(ng-click='closeQuest(); $close()')=env.t('cancel')
|
||||
button.btn.btn-primary(ng-click='questInit(); $close()')
|
||||
button.btn.btn-primary(ng-click='questInit()')
|
||||
| {{:: party.memberCount > 1 ? env.t('inviteParty') : env.t('startQuest')}}
|
||||
|
||||
script(type='text/ng-template', id='modals/buyQuest.html')
|
||||
|
|
@ -79,8 +79,8 @@ script(type='text/ng-template', id='modals/questInvitation.html')
|
|||
quest-rewards(key='{{::user.party.quest.key}}', header=env.t('rewards'))
|
||||
.modal-footer
|
||||
button.btn.btn-default(ng-click='questHold = true; $close()')=env.t('askLater')
|
||||
button.btn.btn-default(ng-click='questReject(party); $close()')=env.t('reject')
|
||||
button.btn.btn-primary(ng-click='questAccept(party); $close()')=env.t('accept')
|
||||
button.btn.btn-default(ng-click='questReject(); $close()')=env.t('reject')
|
||||
button.btn.btn-primary(ng-click='questAccept(); $close()')=env.t('accept')
|
||||
|
||||
script(type='text/ng-template', id='modals/questDrop.html')
|
||||
.quest-icon.pull-right(class='inventory_quest_scroll_{{::selectedQuest.key}}')
|
||||
|
|
@ -95,7 +95,7 @@ script(type='text/ng-template', id='modals/questDrop.html')
|
|||
.modal-footer
|
||||
button.btn.btn-default(ng-click='closeQuest(); $close()')=env.t('questLater')
|
||||
button.btn.btn-primary(ng-click='inviteOrStartParty(group); $close()', ng-if='!party.members')=env.t('startAParty')
|
||||
button.btn.btn-primary(ng-click='questInit(); $close()', ng-if='party.members')=env.t('inviteParty')
|
||||
button.btn.btn-primary(ng-click='questInit()', ng-if='party.members')=env.t('inviteParty')
|
||||
|
||||
script(type='text/ng-template', id='modals/ownedQuests.html')
|
||||
.modal-header
|
||||
|
|
|
|||
Loading…
Reference in a new issue