Pull in client side changes for quest routes

This commit is contained in:
Blade Barringer
2015-09-15 09:32:24 -05:00
parent 38e07246da
commit b32e521c56
9 changed files with 620 additions and 292 deletions

View File

@@ -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() { describe('#hasAllTimeTravelerItems', function() {
it('returns false if there are items left in the time traveler store', function() { it('returns false if there are items left in the time traveler store', function() {
expect(scope.hasAllTimeTravelerItems()).to.eql(false); expect(scope.hasAllTimeTravelerItems()).to.eql(false);

View File

@@ -1,7 +1,7 @@
'use strict'; 'use strict';
describe("Party Controller", function() { describe("Party Controller", function() {
var scope, ctrl, user, User, groups, rootScope, $controller; var scope, ctrl, user, User, questsService, groups, rootScope, $controller;
beforeEach(function() { beforeEach(function() {
user = specHelper.newUser(), user = specHelper.newUser(),
@@ -15,7 +15,7 @@ describe("Party Controller", function() {
$provide.value('User', User); $provide.value('User', User);
}); });
inject(function(_$rootScope_, _$controller_, Groups){ inject(function(_$rootScope_, _$controller_, Groups, Quests){
rootScope = _$rootScope_; rootScope = _$rootScope_;
@@ -24,6 +24,7 @@ describe("Party Controller", function() {
$controller = _$controller_; $controller = _$controller_;
groups = Groups; groups = Groups;
questsService = Quests;
// Load RootCtrl to ensure shared behaviors are loaded // Load RootCtrl to ensure shared behaviors are loaded
$controller('RootCtrl', {$scope: scope, User: User}); $controller('RootCtrl', {$scope: scope, User: User});
@@ -33,129 +34,180 @@ describe("Party Controller", function() {
}); });
describe('questAccept', function() { describe('questAccept', function() {
it('calls Groups.questAccept', function() { beforeEach(function() {
var party = {}; scope.group = {
var groupSpy = sandbox.stub(groups, "questAccept", function(){return true;}); quest: { members: { 'user-id': true } }
scope.questAccept(party); };
groupSpy.should.have.been.calledOnce; 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() { describe('questReject', function() {
it('calls Groups.questReject', function() { beforeEach(function() {
var party = {}; scope.group = {
var groupSpy = sandbox.stub(groups, "questReject", function(){return true;}); quest: { members: { 'user-id': true } }
scope.questReject(party); };
groupSpy.should.have.been.calledOnce; 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() { describe('questCancel', function() {
var party, cancelSpy, windowSpy; var party, cancelSpy, windowSpy;
beforeEach(function() { beforeEach(function() {
party = {}; sandbox.stub(questsService, 'sendAction').returns({
cancelSpy = sandbox.stub(groups, "questCancel", function(){return true;}); then: sandbox.stub().yields({members: {another: true}})
});
}); });
afterEach(function() { it('calls Quests.sendAction when alert box is confirmed', function() {
windowSpy.restore(); sandbox.stub(window, "confirm").returns(true);
cancelSpy.restore();
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() { it('does not call Quests.sendAction when alert box is not confirmed', function() {
windowSpy = sandbox.stub(window, "confirm", function(){return true}); sandbox.stub(window, "confirm").returns(false);
scope.questCancel(party); scope.questCancel();
windowSpy.should.have.been.calledOnce;
windowSpy.should.have.been.calledWith(window.env.t('sureCancel'));
cancelSpy.should.have.been.calledOnce;
});
it('does not call Groups.questCancel when alert box is not confirmed', function() { expect(window.confirm).to.be.calledOnce;
windowSpy = sandbox.stub(window, "confirm", function(){return false}); expect(questsService.sendAction).to.not.be.called;
scope.questCancel(party);
windowSpy.should.have.been.calledOnce;
cancelSpy.should.not.have.been.calledOnce;
}); });
}); });
describe('questAbort', function() { describe('questAbort', function() {
var party, abortSpy, windowSpy;
beforeEach(function() { beforeEach(function() {
party = {}; sandbox.stub(questsService, 'sendAction').returns({
abortSpy = sandbox.stub(groups, "questAbort", function(){return true;}); then: sandbox.stub().yields({members: {another: true}})
});
}); });
afterEach(function() { it('calls Quests.sendAction when two alert boxes are confirmed', function() {
windowSpy.restore(); sandbox.stub(window, "confirm", function(){return true});
abortSpy.restore();
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() { it('does not call Quests.sendAction when first alert box is not confirmed', function() {
windowSpy = sandbox.stub(window, "confirm", function(){return true}); sandbox.stub(window, "confirm", function(){return false});
scope.questAbort(party); scope.questAbort();
windowSpy.should.have.been.calledTwice;
windowSpy.should.have.been.calledWith(window.env.t('sureAbort')); expect(window.confirm).to.be.calledOnce;
windowSpy.should.have.been.calledWith(window.env.t('doubleSureAbort')); expect(window.confirm).to.be.calledWith(window.env.t('sureAbort'));
abortSpy.should.have.been.calledOnce; 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() { it('does not call Quests.sendAction when first alert box is confirmed but second one is not', 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() {
// Hack to confirm first window, but not second // Hack to confirm first window, but not second
// Should not be necessary when we upgrade sinon
var shouldReturn = false; var shouldReturn = false;
windowSpy = sandbox.stub(window, "confirm", function(){ sandbox.stub(window, 'confirm', function(){
shouldReturn = !shouldReturn; shouldReturn = !shouldReturn;
return shouldReturn; return shouldReturn;
}); });
scope.questAbort(party); scope.questAbort();
windowSpy.should.have.been.calledTwice;
windowSpy.should.have.been.calledWith(window.env.t('sureAbort')); expect(window.confirm).to.be.calledTwice;
windowSpy.should.have.been.calledWith(window.env.t('doubleSureAbort')); expect(window.confirm).to.be.calledWith(window.env.t('sureAbort'));
abortSpy.should.not.have.been.calledOnce; expect(window.confirm).to.be.calledWith(window.env.t('doubleSureAbort'));
expect(questsService.sendAction).to.not.be.called;
}); });
}); });
describe('#questLeave', function() { describe('#questLeave', function() {
var party, leaveSpy, windowSpy;
beforeEach(function() { beforeEach(function() {
party = {};
scope.group = { scope.group = {
quest: { members: { 'user-id': true } } quest: { members: { 'user-id': true } }
}; };
leaveSpy = sandbox.stub(groups, 'questLeave').returns({ sandbox.stub(questsService, 'sendAction').returns({
then: sandbox.stub().yields() then: sandbox.stub().yields({members: {another: true}})
}); });
}); });
it('calls Groups.questLeave when alert box is confirmed', function() { it('calls Quests.sendAction when alert box is confirmed', function() {
windowSpy = sandbox.stub(window, "confirm").returns(true); sandbox.stub(window, "confirm").returns(true);
scope.questLeave(party); scope.questLeave();
windowSpy.should.have.been.calledOnce;
windowSpy.should.have.been.calledWith(window.env.t('sureLeave')); expect(window.confirm).to.be.calledOnce;
leaveSpy.should.have.been.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() { it('does not call Quests.sendAction when alert box is not confirmed', function() {
windowSpy = sandbox.stub(window, "confirm").returns(false); sandbox.stub(window, "confirm").returns(false);
scope.questLeave(party); scope.questLeave();
windowSpy.should.have.been.calledOnce;
leaveSpy.should.not.have.been.calledOnce; 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);
});
});
}); });

View File

@@ -39,67 +39,4 @@ describe('groupServices', function() {
groups.myGuilds(); groups.myGuilds();
$httpBackend.flush(); $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');
});
});
}
});
}); });

View File

@@ -1,7 +1,7 @@
'use strict'; 'use strict';
describe('Quests Service', function() { describe('Quests Service', function() {
var scope, rootScope, groupsService, quest, questsService, user, content; var groupsService, quest, questsService, user, content, resolveSpy, rejectSpy;
beforeEach(function() { beforeEach(function() {
user = specHelper.newUser(); user = specHelper.newUser();
@@ -16,105 +16,365 @@ describe('Quests Service', function() {
$provide.value('User', {user: user}); $provide.value('User', {user: user});
}); });
inject(function($rootScope, $controller, Quests, Groups, Content) { inject(function(Quests, Groups, Content) {
scope = $rootScope.$new();
rootScope = $rootScope;
$controller('RootCtrl', {$scope: scope, User: {user: user}});
questsService = Quests; questsService = Quests;
groupsService = Groups; groupsService = Groups;
content = Content; content = Content;
}); });
sandbox.stub(groupsService, 'inviteOrStartParty'); sandbox.stub(groupsService, 'inviteOrStartParty');
sandbox.stub(rootScope, 'openModal'); sandbox.stub(window,'confirm');
sandbox.stub(window,'confirm',function(){return true});
sandbox.stub(window,'alert'); 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() { expect(questsService.lockQuest(quest)).to.be.ok;
user.stats.lvl = 15; });
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() { expect(questsService.lockQuest(quest,true)).to.not.be.ok;
user.stats.lvl = 15; });
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() { expect(questsService.lockQuest(quest)).to.not.be.ok;
user.stats.lvl = 20; });
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() { expect(questsService.lockQuest(quest)).to.be.ok;
quest.previous = 'priorQuest'; });
user.stats.lvl = 25;
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() { expect(questsService.lockQuest(quest)).to.not.be.ok;
quest.previous = 'priorQuest'; });
user.stats.lvl = 25; });
user.achievements.quests.priorQuest = 1;
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() { it('prompts user to invite friends to party for invite reward quests', function() {
questsService.buyQuest('basilist'); questsService.buyQuest('basilist');
expect(window.confirm).to.have.been.calledOnce; expect(window.confirm).to.be.calledOnce;
expect(groupsService.inviteOrStartParty).to.have.been.calledOnce; expect(window.confirm).to.be.calledWith(env.t('mustInviteFriend'));
expect(rootScope.openModal).to.have.been.notCalled;
}); });
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.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; scope.$apply();
expect(rootScope.openModal).to.have.been.notCalled;
}); });
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; 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; scope.$apply();
expect(rootScope.openModal).to.have.been.notCalled;
}); });
it('opens purchase modal if Gem quest prerequisites are met', function() { it('allows user to buy quest if they meet level requirement', function(done) {
user.stats.lvl = 100; user.stats.lvl = 30;
user.achievements.quests.atom1 = 2;
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); scope.$apply();
expect(rootScope.openModal).to.have.been.calledOnce;
expect(rootScope.openModal).to.have.been.calledWith('buyQuest');
}); });
});
it('opens purchase modal if quest is Gold-purchasable', function() { context('gold purchasable quests', function() {
questsService.buyQuest('dilatoryDistress1'); 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); scope.$apply();
expect(rootScope.openModal).to.have.been.calledOnce; });
expect(rootScope.openModal).to.have.been.calledWith('buyQuest'); });
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 endpoint 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();
});
});
}); });

View File

@@ -39,21 +39,9 @@
leave: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/leave'}, leave: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/leave'},
invite: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/invite'}, invite: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/invite'},
removeMember: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/removeMember'}, removeMember: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/removeMember'},
questAccept: {method: "POST", url: ApiUrl.get() + '/api/v2/groups/:gid/questAccept'}, startQuest: {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'}
}); });
function _syncUser() {
User.sync();
}
function _logError(err) {
console.log(err);
}
function party(cb) { function party(cb) {
if (!data.party) return (data.party = Group.get({gid: 'party'}, cb)); if (!data.party) return (data.party = Group.get({gid: 'party'}, cb));
return (cb) ? cb(party) : data.party; return (cb) ? cb(party) : data.party;
@@ -75,36 +63,6 @@
return data.tavern; 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) { function inviteOrStartParty(group) {
Analytics.track({'hitType':'event','eventCategory':'button','eventAction':'click','eventLabel':'Invite Friends'}); Analytics.track({'hitType':'event','eventCategory':'button','eventAction':'click','eventLabel':'Invite Friends'});
if (group.type === "party" || $location.$$path === "/options/groups/party") { if (group.type === "party" || $location.$$path === "/options/groups/party") {
@@ -125,11 +83,6 @@
publicGuilds: publicGuilds, publicGuilds: publicGuilds,
myGuilds: myGuilds, myGuilds: myGuilds,
tavern: tavern, tavern: tavern,
questAccept: questAccept,
questReject: questReject,
questAbort: questAbort,
questLeave: questLeave,
questCancel: questCancel,
inviteOrStartParty: inviteOrStartParty, inviteOrStartParty: inviteOrStartParty,
data: data, data: data,

View File

@@ -6,14 +6,17 @@
.factory('Quests', questsFactory); .factory('Quests', questsFactory);
questsFactory.$inject = [ questsFactory.$inject = [
'$rootScope', '$http',
'$state',
'$q',
'ApiUrl',
'Content', 'Content',
'Groups', 'Groups',
'User', 'User',
'Analytics' 'Analytics'
]; ];
function questsFactory($rootScope,Content,Groups,User,Analytics) { function questsFactory($http, $state, $q, ApiUrl, Content, Groups, User, Analytics) {
var user = User.user; var user = User.user;
var party = Groups.party(); var party = Groups.party();
@@ -26,21 +29,39 @@
return (quest.previous); return (quest.previous);
} }
function buyQuest(quest) { function _preventQuestModal(quest) {
var item = Content.quests[quest]; if (!quest) {
return 'No quest with that key found';
}
if (item.unlockCondition && item.unlockCondition.condition === 'party invite') { if (quest.previous && (!user.achievements.quests || (user.achievements.quests && !user.achievements.quests[quest.previous]))){
if (!confirm(window.env.t('mustInviteFriend'))) return; alert(window.env.t('unlockByQuesting', {title: Content.quests[quest.previous].text()}));
return Groups.inviteOrStartParty(party); 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}));
} function buyQuest(quest) {
$rootScope.selectedQuest = item; return $q(function(resolve, reject) {
$rootScope.openModal('buyQuest', {controller:'InventoryCtrl'}); 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) { function questPopover(quest) {
@@ -71,37 +92,52 @@
} }
function showQuest(quest) { function showQuest(quest) {
var item = Content.quests[quest]; return $q(function(resolve, reject) {
var completedPrevious = !item.previous || (User.user.achievements.quests && User.user.achievements.quests[item.previous]); var item = Content.quests[quest];
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'});
}
function closeQuest(){ var preventQuestModal = _preventQuestModal(item);
$rootScope.selectedQuest = undefined; if (preventQuestModal) {
} return reject(preventQuestModal);
}
function questInit(){ resolve(item);
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(); function initQuest(key) {
$rootScope.$state.go('options.social.party'); 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) {
Analytics.updateUser({
partyID: party._id,
partySize: party.memberCount
});
var quest = response.data.quest;
resolve(quest);
});;
}); });
closeQuest();
} }
return { return {
lockQuest: lockQuest, lockQuest: lockQuest,
buyQuest: buyQuest, buyQuest: buyQuest,
questPopover: questPopover, questPopover: questPopover,
sendAction: sendAction,
showQuest: showQuest, showQuest: showQuest,
closeQuest: closeQuest, initQuest: initQuest
questInit: questInit
} }
} }
}()); }());

View File

@@ -1,4 +1,4 @@
div(ng-if='group.quest.active==true') div(ng-if='group.quest.active===true')
unless tavern unless tavern
tabset tabset
tab(heading=env.t('questDetails')) tab(heading=env.t('questDetails'))
@@ -20,7 +20,7 @@ div(ng-if='group.quest.active==true')
include ./ianQuestInfo include ./ianQuestInfo
unless tavern unless tavern
button.btn.btn-sm.btn-warning(ng-if=':: (group.quest.leader && group.quest.leader==user._id && isMemberOfRunningQuest(group.quest.leader,group))', button.btn.btn-sm.btn-warning(ng-if='::canEditQuest(party)',
ng-click='questAbort(party)')=env.t('abort') 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)', 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')

View File

@@ -1,4 +1,4 @@
div(ng-if='group.quest.active==false') div(ng-if='group.quest.active===false')
tabset tabset
tab(heading=env.t('invitations')) tab(heading=env.t('invitations'))
+participants(false) +participants(false)
@@ -22,9 +22,9 @@ div(ng-if='group.quest.active==false')
p=env.t('questStart') p=env.t('questStart')
span(ng-if='user.party.quest.RSVPNeeded') 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-success(ng-click='questAccept()')=env.t('accept')
button.btn.btn-sm.btn-danger(ng-click='questReject(party)')=env.t('reject') 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)') span(ng-if='::canEditQuest(party)')
button.btn.btn-sm.btn-warning(ng-click='party.$questAccept({"force":true})')=env.t('begin') button.btn.btn-sm.btn-warning(ng-click='party.$startQuest({"force":true})')=env.t('begin')
button.btn.btn-sm.btn-danger(ng-click='questCancel(party)')=env.t('cancel') button.btn.btn-sm.btn-danger(ng-click='questCancel()')=env.t('cancel')

View File

@@ -43,7 +43,7 @@ script(type='text/ng-template', id='modals/showQuest.html')
p=env.t('questWarning') p=env.t('questWarning')
.modal-footer .modal-footer
button.btn.btn-default(ng-click='closeQuest(); $close()')=env.t('cancel') 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')}} | {{:: party.memberCount > 1 ? env.t('inviteParty') : env.t('startQuest')}}
script(type='text/ng-template', id='modals/buyQuest.html') 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')) quest-rewards(key='{{::user.party.quest.key}}', header=env.t('rewards'))
.modal-footer .modal-footer
button.btn.btn-default(ng-click='questHold = true; $close()')=env.t('askLater') 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-default(ng-click='questReject(); $close()')=env.t('reject')
button.btn.btn-primary(ng-click='questAccept(party); $close()')=env.t('accept') button.btn.btn-primary(ng-click='questAccept(); $close()')=env.t('accept')
script(type='text/ng-template', id='modals/questDrop.html') script(type='text/ng-template', id='modals/questDrop.html')
.quest-icon.pull-right(class='inventory_quest_scroll_{{::selectedQuest.key}}') .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 .modal-footer
button.btn.btn-default(ng-click='closeQuest(); $close()')=env.t('questLater') 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='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') script(type='text/ng-template', id='modals/ownedQuests.html')
.modal-header .modal-header