mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-19 07:37:25 +01:00
Refactor quest functions and add tests
This commit is contained in:
@@ -310,3 +310,132 @@ describe("CopyMessageModal controller", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Party Controller", function() {
|
||||||
|
var scope, ctrl, user, User, groups, $rootScope, $controller;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
user = specHelper.newUser(),
|
||||||
|
user._id = "unique-user-id";
|
||||||
|
User = {
|
||||||
|
user: user,
|
||||||
|
sync: sinon.spy
|
||||||
|
}
|
||||||
|
|
||||||
|
module(function($provide) {
|
||||||
|
$provide.value('User', User);
|
||||||
|
});
|
||||||
|
|
||||||
|
inject(function(_$rootScope_, _$controller_, Groups){
|
||||||
|
|
||||||
|
$rootScope = _$rootScope_;
|
||||||
|
|
||||||
|
scope = _$rootScope_.$new();
|
||||||
|
|
||||||
|
$controller = _$controller_;
|
||||||
|
|
||||||
|
groups = Groups;
|
||||||
|
|
||||||
|
// Load RootCtrl to ensure shared behaviors are loaded
|
||||||
|
$controller('RootCtrl', {$scope: scope, User: User});
|
||||||
|
|
||||||
|
ctrl = $controller('PartyCtrl', {$scope: scope, User: User});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('questAccept', function() {
|
||||||
|
it('calls Groups.questAccept', function() {
|
||||||
|
var party = {};
|
||||||
|
var groupSpy = sinon.stub(groups, "questAccept", function(){return true;});
|
||||||
|
scope.questAccept(party);
|
||||||
|
groupSpy.should.have.been.calledOnce;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('questReject', function() {
|
||||||
|
it('calls Groups.questReject', function() {
|
||||||
|
var party = {};
|
||||||
|
var groupSpy = sinon.stub(groups, "questReject", function(){return true;});
|
||||||
|
scope.questReject(party);
|
||||||
|
groupSpy.should.have.been.calledOnce;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('questCancel', function() {
|
||||||
|
var party, cancelSpy, windowSpy;
|
||||||
|
beforeEach(function() {
|
||||||
|
party = {};
|
||||||
|
cancelSpy = sinon.stub(groups, "questCancel", function(){return true;});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
windowSpy.restore();
|
||||||
|
cancelSpy.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls Groups.questCancel when alert box is confirmed', function() {
|
||||||
|
windowSpy = sinon.stub(window, "confirm", function(){return true});
|
||||||
|
|
||||||
|
scope.questCancel(party);
|
||||||
|
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 confirmed', function() {
|
||||||
|
windowSpy = sinon.stub(window, "confirm", function(){return false});
|
||||||
|
|
||||||
|
scope.questCancel(party);
|
||||||
|
windowSpy.should.have.been.calledOnce;
|
||||||
|
cancelSpy.should.not.have.been.calledOnce;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('questAbort', function() {
|
||||||
|
var party, abortSpy, windowSpy;
|
||||||
|
beforeEach(function() {
|
||||||
|
party = {};
|
||||||
|
abortSpy = sinon.stub(groups, "questAbort", function(){return true;});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
windowSpy.restore();
|
||||||
|
abortSpy.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls Groups.questAbort when two alert boxes are confirmed', function() {
|
||||||
|
windowSpy = sinon.stub(window, "confirm", function(){return true});
|
||||||
|
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not call Groups.questAbort when first alert box is not confirmed', function() {
|
||||||
|
windowSpy = sinon.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
|
||||||
|
var shouldReturn = false;
|
||||||
|
windowSpy = sinon.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;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
describe('groupServices', function() {
|
describe('groupServices', function() {
|
||||||
var $httpBackend, $http, groups;
|
var $httpBackend, $http, groups, user;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
module(function($provide) {
|
module(function($provide) {
|
||||||
@@ -11,6 +11,8 @@ describe('groupServices', function() {
|
|||||||
inject(function(_$httpBackend_, Groups, User) {
|
inject(function(_$httpBackend_, Groups, User) {
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
groups = Groups;
|
groups = Groups;
|
||||||
|
user = User;
|
||||||
|
user.sync = function(){};
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -38,4 +40,100 @@ describe('groupServices', function() {
|
|||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
context('quest function wrappers', function() {
|
||||||
|
var successPromise = function() {
|
||||||
|
return {
|
||||||
|
then: function(success, failure) {
|
||||||
|
success();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var successParty = {
|
||||||
|
$questAccept: successPromise,
|
||||||
|
$questReject: successPromise,
|
||||||
|
$questCancel: successPromise,
|
||||||
|
$questAbort: successPromise
|
||||||
|
}
|
||||||
|
|
||||||
|
var failPromise = function() {
|
||||||
|
return {
|
||||||
|
then: function(success, failure) {
|
||||||
|
failure('fail');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var failParty = {
|
||||||
|
$questAccept: failPromise,
|
||||||
|
$questReject: failPromise,
|
||||||
|
$questCancel: failPromise,
|
||||||
|
$questAbort: failPromise
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
sinon.spy(user, 'sync');
|
||||||
|
sinon.stub(console, 'log', function(arg) { return true; });
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
user.sync.restore();
|
||||||
|
console.log.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('questAccept', function() {
|
||||||
|
it('syncs user if $questAccept succeeds', function() {
|
||||||
|
groups.questAccept(successParty);
|
||||||
|
user.sync.should.have.been.calledOnce;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not sync user if $questAccept fails', function() {
|
||||||
|
groups.questAccept(failParty);
|
||||||
|
user.sync.should.not.have.been.calledOnce;
|
||||||
|
console.log.should.have.been.calledWith('fail');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('questReject', function() {
|
||||||
|
it('syncs user if $questReject succeeds', function() {
|
||||||
|
groups.questReject(successParty);
|
||||||
|
user.sync.should.have.been.calledOnce;
|
||||||
|
console.log.should.not.have.been.called;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not sync user if $questReject fails', function() {
|
||||||
|
groups.questReject(failParty);
|
||||||
|
user.sync.should.not.have.been.calledOnce;
|
||||||
|
console.log.should.have.been.calledWith('fail');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('questCancel', function() {
|
||||||
|
it('syncs user if $questCancel succeeds', function() {
|
||||||
|
groups.questCancel(successParty);
|
||||||
|
user.sync.should.have.been.calledOnce;
|
||||||
|
console.log.should.not.have.been.called;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not sync user if $questCancel fails', function() {
|
||||||
|
groups.questCancel(failParty);
|
||||||
|
user.sync.should.not.have.been.calledOnce;
|
||||||
|
console.log.should.have.been.calledWith('fail');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('questAbort', function() {
|
||||||
|
it('syncs user if $questAbort succeeds', function() {
|
||||||
|
groups.questAbort(successParty);
|
||||||
|
user.sync.should.have.been.calledOnce;
|
||||||
|
console.log.should.not.have.been.called;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not sync user if $questAbort fails', function() {
|
||||||
|
groups.questAbort(failParty);
|
||||||
|
user.sync.should.not.have.been.calledOnce;
|
||||||
|
console.log.should.have.been.calledWith('fail');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -569,33 +569,23 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', '
|
|||||||
User.set({'invitations.party':{}});
|
User.set({'invitations.party':{}});
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.questCancel = function(){
|
$scope.questCancel = function(party){
|
||||||
if (!confirm(window.env.t('sureCancel'))) return;
|
if (!confirm(window.env.t('sureCancel'))) return;
|
||||||
$rootScope.party.$questCancel();
|
Groups.questCancel(party);
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.questAbort = function(){
|
$scope.questAbort = function(party){
|
||||||
if (!confirm(window.env.t('sureAbort'))) return;
|
if (!confirm(window.env.t('sureAbort'))) return;
|
||||||
if (!confirm(window.env.t('doubleSureAbort'))) return;
|
if (!confirm(window.env.t('doubleSureAbort'))) return;
|
||||||
$rootScope.party.$questAbort();
|
Groups.questAbort(party);
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.questAccept = function(party){
|
$scope.questAccept = function(party){
|
||||||
party.$questAccept()
|
Groups.questAccept(party);
|
||||||
.then(function(res) {
|
|
||||||
User.sync();
|
|
||||||
}, function(err) {
|
|
||||||
console.log(err);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.questReject = function(party){
|
$scope.questReject = function(party){
|
||||||
party.$questReject()
|
Groups.questReject(party);
|
||||||
.then(function(res) {
|
|
||||||
User.sync();
|
|
||||||
}, function(err) {
|
|
||||||
console.log(err);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -40,6 +40,13 @@ function(ApiUrl, $resource, $q, $http, User, Challenges) {
|
|||||||
// Defer loading everything until they're requested
|
// Defer loading everything until they're requested
|
||||||
var data = {party: undefined, myGuilds: undefined, publicGuilds: undefined, tavern: undefined};
|
var data = {party: undefined, myGuilds: undefined, publicGuilds: undefined, tavern: undefined};
|
||||||
|
|
||||||
|
var syncUser = function(res) {
|
||||||
|
User.sync();
|
||||||
|
}
|
||||||
|
var logError = function(err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
party: function(cb){
|
party: function(cb){
|
||||||
if (!data.party) return (data.party = Group.get({gid: 'party'}, cb));
|
if (!data.party) return (data.party = Group.get({gid: 'party'}, cb));
|
||||||
@@ -65,6 +72,26 @@ function(ApiUrl, $resource, $q, $http, User, Challenges) {
|
|||||||
if (User.user.newMessages) delete User.user.newMessages[gid];
|
if (User.user.newMessages) delete User.user.newMessages[gid];
|
||||||
},
|
},
|
||||||
|
|
||||||
|
questAccept: function(party){
|
||||||
|
party.$questAccept()
|
||||||
|
.then(syncUser, logError);
|
||||||
|
},
|
||||||
|
|
||||||
|
questReject: function(party){
|
||||||
|
party.$questReject()
|
||||||
|
.then(syncUser, logError);
|
||||||
|
},
|
||||||
|
|
||||||
|
questCancel: function(party){
|
||||||
|
party.$questCancel()
|
||||||
|
.then(syncUser, logError);
|
||||||
|
},
|
||||||
|
|
||||||
|
questAbort: function(party){
|
||||||
|
party.$questAbort()
|
||||||
|
.then(syncUser, logError);
|
||||||
|
},
|
||||||
|
|
||||||
// Pass reference to party, myGuilds, publicGuilds, tavern; inside data in order to
|
// Pass reference to party, myGuilds, publicGuilds, tavern; inside data in order to
|
||||||
// be able to modify them directly (otherwise will be stick with cached version)
|
// be able to modify them directly (otherwise will be stick with cached version)
|
||||||
data: data,
|
data: data,
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ mixin boss(tavern, mobile)
|
|||||||
button.btn.btn-sm.btn-warning(ng-if=':: group.quest.leader && group.quest.leader==user._id && isMemberOfGroup(group.quest.leader,group) && isMemberOfPendingQuest(group.quest.leader,group)', ng-click='party.$questAccept({"force":true})')=env.t('begin')
|
button.btn.btn-sm.btn-warning(ng-if=':: group.quest.leader && group.quest.leader==user._id && isMemberOfGroup(group.quest.leader,group) && isMemberOfPendingQuest(group.quest.leader,group)', ng-click='party.$questAccept({"force":true})')=env.t('begin')
|
||||||
// // only the quest owner sees the cancel button UNLESS the quest owner is no longer in the quest/party and then everyone sees it:
|
// // only the quest owner sees the cancel button UNLESS the quest owner is no longer in the quest/party and then everyone sees it:
|
||||||
// This is commented-out until we have time to work out why it fails intermittently on the website and always on the mobile app (https://github.com/HabitRPG/habitrpg/issues/4074):
|
// This is commented-out until we have time to work out why it fails intermittently on the website and always on the mobile app (https://github.com/HabitRPG/habitrpg/issues/4074):
|
||||||
// button.btn.btn-sm.btn-danger(ng-if=':: (group.quest.leader && group.quest.leader==user._id && isMemberOfGroup(group.quest.leader,group) && isMemberOfPendingQuest(group.quest.leader,group)) || (! group.quest.leader || ! isMemberOfGroup(group.quest.leader,group) || ! isMemberOfPendingQuest(group.quest.leader,group))', ng-click='questCancel()')=env.t('cancel')
|
// button.btn.btn-sm.btn-danger(ng-if=':: (group.quest.leader && group.quest.leader==user._id && isMemberOfGroup(group.quest.leader,group) && isMemberOfPendingQuest(group.quest.leader,group)) || (! group.quest.leader || ! isMemberOfGroup(group.quest.leader,group) || ! isMemberOfPendingQuest(group.quest.leader,group))', ng-click='questCancel(party)')=env.t('cancel')
|
||||||
// only the quest owner sees the cancel button:
|
// only the quest owner sees the cancel button:
|
||||||
button.btn.btn-sm.btn-danger(ng-if=':: (group.quest.leader && group.quest.leader==user._id && isMemberOfGroup(group.quest.leader,group) && isMemberOfPendingQuest(group.quest.leader,group))', ng-click='questCancel()')=env.t('cancel')
|
button.btn.btn-sm.btn-danger(ng-if=':: (group.quest.leader && group.quest.leader==user._id && isMemberOfGroup(group.quest.leader,group) && isMemberOfPendingQuest(group.quest.leader,group))', ng-click='questCancel(party)')=env.t('cancel')
|
||||||
|
|
||||||
div(ng-if='group.quest.active==true')
|
div(ng-if='group.quest.active==true')
|
||||||
div(ng-if='::Content.quests[group.quest.key].boss',ng-init='boss=Content.quests[group.quest.key].boss;progress=group.quest.progress')
|
div(ng-if='::Content.quests[group.quest.key].boss',ng-init='boss=Content.quests[group.quest.key].boss;progress=group.quest.progress')
|
||||||
@@ -109,6 +109,6 @@ mixin boss(tavern, mobile)
|
|||||||
unless tavern
|
unless tavern
|
||||||
// // only the quest owner sees the abort button UNLESS the quest owner is no longer in the quest/party and then everyone sees it:
|
// // only the quest owner sees the abort button UNLESS the quest owner is no longer in the quest/party and then everyone sees it:
|
||||||
// This is commented-out until we have time to work out why it fails intermittently on the website and always on the mobile app (https://github.com/HabitRPG/habitrpg/issues/4074):
|
// This is commented-out until we have time to work out why it fails intermittently on the website and always on the mobile app (https://github.com/HabitRPG/habitrpg/issues/4074):
|
||||||
// button.btn.btn-sm.btn-warning(ng-if=':: (group.quest.leader && group.quest.leader==user._id && isMemberOfGroup(group.quest.leader,group) && isMemberOfRunningQuest(group.quest.leader,group)) || ! group.quest.leader || ! isMemberOfGroup(group.quest.leader,group) || ! isMemberOfRunningQuest(group.quest.leader,group)', ng-click='questAbort()')=env.t('abort')
|
// button.btn.btn-sm.btn-warning(ng-if=':: (group.quest.leader && group.quest.leader==user._id && isMemberOfGroup(group.quest.leader,group) && isMemberOfRunningQuest(group.quest.leader,group)) || ! group.quest.leader || ! isMemberOfGroup(group.quest.leader,group) || ! isMemberOfRunningQuest(group.quest.leader,group)', ng-click='questAbort(party)')=env.t('abort')
|
||||||
// only the quest owner sees the abort button:
|
// only the quest owner sees the abort button:
|
||||||
button.btn.btn-sm.btn-warning(ng-if=':: (group.quest.leader && group.quest.leader==user._id && isMemberOfGroup(group.quest.leader,group) && isMemberOfRunningQuest(group.quest.leader,group))', ng-click='questAbort()')=env.t('abort')
|
button.btn.btn-sm.btn-warning(ng-if=':: (group.quest.leader && group.quest.leader==user._id && isMemberOfGroup(group.quest.leader,group) && isMemberOfRunningQuest(group.quest.leader,group))', ng-click='questAbort(party)')=env.t('abort')
|
||||||
|
|||||||
Reference in New Issue
Block a user