'use strict'; describe("Party Controller", function() { var scope, ctrl, user, User, questsService, groups, rootScope, $controller, deferred; var party; beforeEach(function() { user = specHelper.newUser(), user._id = "unique-user-id"; User = { user: user, sync: sandbox.spy(), set: sandbox.spy() }; party = specHelper.newGroup({ _id: "unique-party-id", type: 'party', members: ['leader-id'] // Ensure we wouldn't pass automatically. }); module(function($provide) { $provide.value('User', User); }); inject(function(_$rootScope_, _$controller_, Groups, Quests, _$q_){ rootScope = _$rootScope_; scope = _$rootScope_.$new(); $controller = _$controller_; groups = Groups; questsService = Quests; // Load RootCtrl to ensure shared behaviors are loaded $controller('RootCtrl', {$scope: scope, User: User}); ctrl = $controller('PartyCtrl', {$scope: scope, User: User}); }); }); describe('initialization', function() { var groupResponse; function initializeControllerWithStubbedState() { inject(function(_$state_) { var state = _$state_; sandbox.stub(state, 'is').returns(true); var syncParty = sinon.stub(groups.Group, 'syncParty') syncParty.returns(Promise.resolve(groupResponse)); $controller('PartyCtrl', { $scope: scope, $state: state, User: User }); expect(state.is).to.be.calledOnce; // ensure initialization worked as desired }); }; beforeEach(function() { sandbox.stub(rootScope, 'openModal'); }); context('party has 1 member', function() { it('awards no new achievements', function() { groupResponse = {_id: "test", type: "party", memberCount: 1}; initializeControllerWithStubbedState(); expect(User.set).to.not.be.called; expect(rootScope.openModal).to.not.be.called; }); }); context('party has 2 members', function() { context('user does not have "Party Up" achievement', function() { it('awards "Party Up" achievement', function(done) { groupResponse = {_id: "test", type: "party", memberCount: 2}; initializeControllerWithStubbedState(); setTimeout(function() { expect(User.set).to.be.calledOnce; expect(User.set).to.be.calledWith( { 'achievements.partyUp': true } ); expect(rootScope.openModal).to.be.calledOnce; expect(rootScope.openModal).to.be.calledWith('achievements/partyUp'); done(); }, 1000); }); }); }); context('party has 4 members', function() { beforeEach(function() { groupResponse = {_id: "test", type: "party", memberCount: 4}; }); context('user has "Party Up" but not "Party On" achievement', function() { it('awards "Party On" achievement', function(done) { user.achievements.partyUp = true; initializeControllerWithStubbedState(); setTimeout(function(){ expect(User.set).to.be.calledOnce; expect(User.set).to.be.calledWith( { 'achievements.partyOn': true } ); expect(rootScope.openModal).to.be.calledOnce; expect(rootScope.openModal).to.be.calledWith('achievements/partyOn'); done(); }, 1000); }); }); context('user has neither "Party Up" nor "Party On" achievements', function() { it('awards "Party Up" and "Party On" achievements', function(done) { initializeControllerWithStubbedState(); setTimeout(function(){ expect(User.set).to.have.been.called; expect(User.set).to.be.calledWith( { 'achievements.partyUp': true} ); expect(User.set).to.be.calledWith( { 'achievements.partyOn': true} ); expect(rootScope.openModal).to.have.been.called; expect(rootScope.openModal).to.be.calledWith('achievements/partyUp'); expect(rootScope.openModal).to.be.calledWith('achievements/partyOn'); done(); }, 1000); }); }); context('user has both "Party Up" and "Party On" achievements', function() { it('awards no new achievements', function() { user.achievements.partyUp = true; user.achievements.partyOn = true; initializeControllerWithStubbedState(); expect(User.set).to.not.be.called; expect(rootScope.openModal).to.not.be.called; }); }); }); }); describe("create", function() { var partyStub; beforeEach(function () { partyStub = sinon.stub(groups.Group, "create"); partyStub.returns(Promise.resolve(party)); sinon.stub(rootScope, 'hardRedirect'); }); it("creates a new party", function() { var group = { type: 'party', }; scope.create(group); expect(partyStub).to.be.calledOnce; //@TODO: Check user party console.log(User.user.party.id) }); }); describe('questAccept', function() { var sendAction; var memberResponse; beforeEach(function() { scope.group = { quest: { members: { 'user-id': true } } }; memberResponse = {members: {another: true}}; sinon.stub(questsService, 'sendAction') questsService.sendAction.returns(Promise.resolve(memberResponse)); }); it('calls Quests.sendAction', function() { scope.questAccept(); expect(questsService.sendAction).to.be.calledOnce; expect(questsService.sendAction).to.be.calledWith('quests/accept'); }); it('updates quest object with new participants list', function(done) { scope.group.quest = { members: { user: true, another: true } }; setTimeout(function(){ expect(scope.group.quest).to.eql(memberResponse); done(); }, 1000); scope.questAccept(); }); }); describe('questReject', function() { var memberResponse; beforeEach(function() { scope.group = { quest: { members: { 'user-id': true } } }; memberResponse = {members: {another: true}}; var sendAction = sinon.stub(questsService, 'sendAction') sendAction.returns(Promise.resolve(memberResponse)); }); it('calls Quests.sendAction', function() { scope.questReject(); expect(questsService.sendAction).to.be.calledOnce; expect(questsService.sendAction).to.be.calledWith('quests/reject'); }); it('updates quest object with new participants list', function(done) { scope.group.quest = { members: { user: true, another: true } }; setTimeout(function(){ expect(scope.group.quest).to.eql(memberResponse); done(); }, 1000); scope.questReject(); }); }); describe('questCancel', function() { var party, cancelSpy, windowSpy, memberResponse; beforeEach(function() { scope.group = { quest: { members: { 'user-id': true } } }; memberResponse = {members: {another: true}}; sinon.stub(questsService, 'sendAction') questsService.sendAction.returns(Promise.resolve(memberResponse)); }); 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('quests/cancel'); }); it('does not call Quests.sendAction when alert box is not confirmed', function() { sandbox.stub(window, "confirm").returns(false); scope.questCancel(); expect(window.confirm).to.be.calledOnce; expect(questsService.sendAction).to.not.be.called; }); }); describe('questAbort', function() { var memberResponse; beforeEach(function() { scope.group = { quest: { members: { 'user-id': true } } }; memberResponse = {members: {another: true}}; sinon.stub(questsService, 'sendAction') questsService.sendAction.returns(Promise.resolve(memberResponse)); }); 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('quests/abort'); }); it('does not call Quests.sendAction when first alert box is not confirmed', function() { sandbox.stub(window, "confirm", function(){return false}); 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 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; sandbox.stub(window, 'confirm', function(){ shouldReturn = !shouldReturn; return shouldReturn; }); 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 memberResponse; beforeEach(function() { scope.group = { quest: { members: { 'user-id': true } } }; memberResponse = {members: {another: true}}; sinon.stub(questsService, 'sendAction') questsService.sendAction.returns(Promise.resolve(memberResponse)); }); it('calls Quests.sendAction when alert box is confirmed', function() { sandbox.stub(window, "confirm").returns(true); 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('quests/leave'); }); it('does not call Quests.sendAction when alert box is not confirmed', function() { sandbox.stub(window, "confirm").returns(false); scope.questLeave(); expect(window.confirm).to.be.calledOnce; questsService.sendAction.should.not.have.been.calledOnce; }); it('updates quest object with new participants list', function(done) { scope.group.quest = { members: { user: true, another: true } }; sandbox.stub(window, "confirm").returns(true); setTimeout(function(){ expect(scope.group.quest).to.eql(memberResponse); done(); }, 1000); scope.questLeave(); }); }); describe('clickStartQuest', function() { beforeEach(function() { sandbox.stub(rootScope, 'openModal'); sandbox.stub(rootScope.$state, 'go'); }); it('opens quest modal if user has a quest', function() { user.items.quests = { whale: 1 }; scope.clickStartQuest(); expect(rootScope.$state.go).to.not.be.called; expect(rootScope.openModal).to.be.calledOnce; expect(rootScope.openModal).to.be.calledWith( 'ownedQuests', { controller: 'InventoryCtrl' } ); }); it('does not open modal if user has no quests', function() { user.items.quests = { }; scope.clickStartQuest(); expect(rootScope.openModal).to.not.be.called; expect(rootScope.$state.go).to.be.calledOnce; expect(rootScope.$state.go).to.be.calledWith('options.inventory.quests'); }); it('does not open modal if user had quests previously, but does not now', function() { user.items.quests = { whale: 0, atom1: 0 }; scope.clickStartQuest(); expect(rootScope.openModal).to.not.be.called; expect(rootScope.$state.go).to.be.calledOnce; expect(rootScope.$state.go).to.be.calledWith('options.inventory.quests'); }); }); describe('#leaveOldPartyAndJoinNewParty', function() { beforeEach(function() { sandbox.stub(scope, 'join'); groups.data.party = { _id: 'old-party' }; var groupLeave = sandbox.stub(groups.Group, 'leave'); groupLeave.returns(Promise.resolve({})); sandbox.stub(groups, 'party').returns({ _id: 'old-party' }); sandbox.stub(window, 'confirm').returns(true); }); it('does nothing if user declines confirmation', function() { window.confirm.returns(false); scope.leaveOldPartyAndJoinNewParty('some-id', 'some-name'); expect(groups.Group.leave).to.not.be.called; }) it('leaves user\'s current party', function() { scope.leaveOldPartyAndJoinNewParty('some-id', 'some-name'); expect(groups.Group.leave).to.be.calledOnce; expect(groups.Group.leave).to.be.calledWith('old-party', false); }); it('joins the new party', function(done) { scope.leaveOldPartyAndJoinNewParty('some-id', 'some-name'); setTimeout(function() { expect(scope.join).to.be.calledOnce; expect(scope.join).to.be.calledWith({id: 'some-id', name: 'some-name'}); done(); }, 1000); }); }); describe('#canEditQuest', function() { var party; beforeEach(function() { party = specHelper.newGroup({ type: 'party', leader: {}, quest: {} }); scope.group = party; }); 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); }); }); });