UNPKG

gaf-mobile

Version:

GAF mobile Web site

649 lines (594 loc) 19.2 kB
'use strict'; describe('Controller: SignupCtrl', function () { // Vars var $scope, $location, $q, createCtrl; // Mocks var AuthMock, UsersMock, PostProjectMock, CaptchaMock, FacebookMock, AnalyticsMock; var userData = { email: 'chuck@norris.com.au', username: 'chuck' }; var projectData = { title: 'My Project', }; // Load the controller's module beforeEach(module('gafMobileApp')); // Initialize the controller beforeEach(inject(function($controller, $rootScope, _$location_, _$q_) { $location = _$location_; $scope = $rootScope.$new(); $q = _$q_; createCtrl = function() { return $controller('SignupCtrl', { $scope: $scope, $location: $location, Analytics: AnalyticsMock, Auth: AuthMock, Users: UsersMock, Projects: PostProjectMock, Captcha: CaptchaMock, Facebook: FacebookMock }); }; // Mock location $location.host = function () { return 'm.freelancer.com'; }; })); // Create the mock ups beforeEach(function() { AuthMock = jasmine.createSpyObj('Auth', ['isAuthenticated']); UsersMock = jasmine.createSpyObj('Users', ['create', 'createWithFacebook', 'check']); PostProjectMock = jasmine.createSpyObj('Projects', ['getCurrent']); CaptchaMock = jasmine.createSpyObj('Captcha', ['reload', 'get']); FacebookMock = jasmine.createSpyObj('Facebook', ['checkConnected', 'getUserPictureUrl', 'getUser', 'login']); AnalyticsMock = jasmine.createSpyObj('Analytics', ['trackAction', 'trackError']); }); it('should redirect to home when the user is logged in', function() { AuthMock.isAuthenticated.and.returnValue(true); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return false; } }); createCtrl(); expect($location.path()).toBe('/'); }); it('should expand sign up form when user is freelancer', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return false; } }); $location.url('signup?role=freelancer'); var ctrl = createCtrl(); expect(ctrl.showSignupForm).toBeTruthy(); }); it('should load the project details when a project is ready to post', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ get: function() { return projectData; }, isReady: function() { return true; } }); var ctrl = createCtrl(); expect(ctrl.project).toBe(projectData); }); it('should pull facebook data if data available and in fb view', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); $location.url('signup'); FacebookMock.login.and.returnValue($q.when({})); FacebookMock.getUserPictureUrl.and.returnValue($q.when('url')); FacebookMock.getUser.and.returnValue($q.when(userData)); UsersMock.check.and.returnValue($q.when({ recommended_name: 'chuck' })); var ctrl = createCtrl(); ctrl.loadFacebookSignup(); $scope.$digest(); expect(ctrl.state).toBe('facebookSignup'); expect(ctrl.user.username).toBe('chuck'); expect(ctrl.facebookPictureUrl).toBe('url'); }); it('should call the User createWithFacebook for facebook signup', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return false; }, get: function() { return projectData; } }); UsersMock.createWithFacebook.and.returnValue($q.when({})); var ctrl = createCtrl(); ctrl.facebookSignup(userData, {}); $scope.$digest(); expect(UsersMock.createWithFacebook).toHaveBeenCalled(); expect(ctrl.state).toBe('success'); expect(ctrl.user).toBe(userData); }); it('should show default signup view on facebook error', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); FacebookMock.login.and.returnValue($q.reject({ code: 'RANDOM_ERROR' })); var ctrl = createCtrl(); // Set state to non-default ctrl.state = 'facebookSignup'; ctrl.loadFacebookSignup(); $scope.$digest(); expect(ctrl.state).toBe('signup'); }); it('should handle facebook outage by showing fb authentication error', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); $location.url('signup'); FacebookMock.login.and.returnValue($q.reject({ code: 'NOT_AUTHORISED' })); var ctrl = createCtrl(); ctrl.loadFacebookSignup(); $scope.$digest(); expect(ctrl.error.facebookNotAuthorized).toBe(true); }); it('should display connection error if fb not connected and retry is false', function() { PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); FacebookMock.login.and.returnValue( $q.reject({code: 'NOT_CONNECTED'})); var ctrl = createCtrl(); ctrl.loadFacebookSignup(); $scope.$digest(); expect(ctrl.error.facebookNotConnected).toBe(true); }); it('should retry fb connection if fb not connected and retry is true', function() { PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); FacebookMock.login.and.returnValue( $q.reject({code: 'NOT_CONNECTED'})); var ctrl = createCtrl(); ctrl.loadFacebookSignup(false, true); // Set loadFacebookSignup as a spy to test if this will // get called on the retry ctrl.loadFacebookSignup = jasmine.createSpy(); $scope.$digest(); expect(ctrl.loadFacebookSignup).toHaveBeenCalled(); }); it('should display access denied if fb account inaccessible', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); $location.url('signup'); $location.hash('facebook'); FacebookMock.checkConnected.and.returnValue( $q.reject({code: 'ACCESS_DENIED'})); var ctrl = createCtrl(); $scope.$digest(); expect(ctrl.error.facebookAccessDenied).toBe(true); }); it('should redirect to fb-login when facebook email is taken', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); $location.url('signup'); $location.hash('facebook'); FacebookMock.checkConnected.and.returnValue( $q.reject({code: 'EMAIL_TAKEN'})); var ctrl = createCtrl(); $scope.$digest(); expect(ctrl.error.facebookEmailTaken).toBe(true); }); it('should display internal error when custom error is returned', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); $location.url('signup'); $location.hash('facebook'); FacebookMock.checkConnected.and.returnValue( $q.reject({code: 'CUSTOM_ERROR'})); var ctrl = createCtrl(); $scope.$digest(); expect(ctrl.error.facebookUnknownError).toBe('CUSTOM_ERROR'); }); it('should display facebook username taken signup error', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); UsersMock.createWithFacebook.and.returnValue($q.reject({ code: 'USERNAME_TAKEN' })); var ctrl = createCtrl(); ctrl.facebookSignup(userData, {}); $scope.$digest(); expect(UsersMock.createWithFacebook).toHaveBeenCalled(); expect(ctrl.error.usernameTaken).toBe(true); }); it('should display facebook email taken signup error', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); UsersMock.createWithFacebook.and.returnValue($q.reject({ code: 'FACEBOOK_EMAIL_TAKEN' })); var ctrl = createCtrl(); ctrl.facebookSignup(userData, {}); $scope.$digest(); expect(UsersMock.createWithFacebook).toHaveBeenCalled(); expect(ctrl.error.facebookEmailTaken).toBe(true); }); it('should display facebook email taken signup error', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); UsersMock.createWithFacebook.and.returnValue($q.reject({ code: 'ACCESS_DENIED' })); var ctrl = createCtrl(); ctrl.facebookSignup(userData, {}); $scope.$digest(); expect(UsersMock.createWithFacebook).toHaveBeenCalled(); expect(ctrl.error.accessDenied).toBe(true); }); it('should display unknown facebook signup errors', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); UsersMock.createWithFacebook.and.returnValue($q.reject({ code: 'UNKNOWN_ERROR' })); var ctrl = createCtrl(); ctrl.facebookSignup(userData, {}); $scope.$digest(); expect(UsersMock.createWithFacebook).toHaveBeenCalled(); expect(ctrl.error.internalError).toBeDefined(); }); it('should redirect to return URL if it exists and sign up success', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return false; }, get: function() { return projectData; } }); UsersMock.createWithFacebook.and.returnValue($q.when({})); $location.search({ return: '/projects/1234' }); var ctrl = createCtrl(); ctrl.facebookSignup(userData, {}); $scope.$digest(); expect(UsersMock.createWithFacebook).toHaveBeenCalled(); expect($location.url()).toBe('/projects/1234'); }); it('should call the User create for signup', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); UsersMock.create.and.returnValue($q.when(userData)); var ctrl = createCtrl(); ctrl.signup(userData, 'password'); // Promises are evaluated on next digest cycle $scope.$digest(); // third parameter is captcha which will be undefined expect(UsersMock.create).toHaveBeenCalledWith(userData, 'password', undefined); }); it('should redirect to skill select funnel when user is a freelancer', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return false; }, get: function() { return projectData; } }); UsersMock.create.and.returnValue($q.when(userData)); var ctrl = createCtrl(); $location.search('return', '/my-projects'); userData.role = 'freelancer'; ctrl.signup(userData); // Promises are evaluated on next digest cycle $scope.$digest(); expect($location.path()).toBe('/skill-select'); }); it('should show error on username taken sign up failure', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); UsersMock.create.and.returnValue($q.reject({code: 'USERNAME_TAKEN'})); var ctrl = createCtrl(); ctrl.signup(userData); // Promises are evaluated on next digest cycle $scope.$digest(); expect(ctrl.processing).toBe(false); expect(ctrl.state.success).not.toBeDefined(); expect(ctrl.error.usernameTaken).toBe(true); }); it('should show error on email taken sign up failure', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); UsersMock.create.and.returnValue($q.reject({code: 'EMAIL_TAKEN'})); var ctrl = createCtrl(); ctrl.signup(userData); // Promises are evaluated on next digest cycle $scope.$digest(); expect(ctrl.processing).toBe(false); expect(ctrl.state.success).not.toBeDefined(); expect(ctrl.error.emailTaken).toBe(true); }); it('should show error on access denied on signup', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); UsersMock.create.and.returnValue($q.reject({code: 'ACCESS_DENIED'})); var ctrl = createCtrl(); ctrl.signup(userData); // Promises are evaluated on next digest cycle $scope.$digest(); expect(ctrl.processing).toBe(false); expect(ctrl.state.success).not.toBeDefined(); expect(ctrl.error.accessDenied).toBe(true); }); it('should show internal error on unknown sign up failure', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); UsersMock.create.and.returnValue($q.reject({code: 'UNKNOWN_ERROR'})); var ctrl = createCtrl(); ctrl.signup(userData); // Promises are evaluated on next digest cycle $scope.$digest(); expect(ctrl.processing).toBe(false); expect(ctrl.state.success).not.toBeDefined(); expect(ctrl.error.internalError).toBe('UNKNOWN_ERROR'); }); it('should change to captcha state if captcha required', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); UsersMock.create.and.returnValue($q.reject({ message: 'Aie Caramba', code: 'CAPTCHA_REQUIRED' })); var ctrl = createCtrl(); ctrl.signup(userData); // Promises are evaluated on next digest cycle $scope.$digest(); expect(ctrl.captcha).toBe(true); }); it('should show error on invalid captcha on sign up failure and ' + 'reload captcha', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); UsersMock.create.and.returnValue($q.reject({ code: 'INVALID_CAPTCHA' })); var ctrl = createCtrl(); ctrl.captcha = true; ctrl.signup(userData); $scope.$digest(); expect(CaptchaMock.reload).toHaveBeenCalled(); expect(ctrl.state.success).not.toBeDefined(); expect(ctrl.error.invalidCaptcha).toBe(true); }); it('should go to default login page if button is pressed', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); var ctrl = createCtrl(); $scope.$digest(); ctrl.goToLogin(); expect($location.path()).toBe('/login'); expect($location.hash()).toBe(''); }); it('should go to fb login page if button is pressed with fb option', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); var ctrl = createCtrl(); $scope.$digest(); ctrl.goToLogin(true); expect($location.path()).toBe('/login'); expect($location.hash()).toBe('facebook'); }); it('should set role to employer if role not defined on url', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); $location.path('/signup'); var ctrl = createCtrl(); $scope.$digest(); expect(ctrl.user.role).toBe('employer'); }); it('should set role to what it is in the url', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); $location.path('/signup'); $location.search('role', 'freelancer'); var ctrl = createCtrl(); $scope.$digest(); expect(ctrl.user.role).toBe('freelancer'); }); it('should load fb signup if url contains facebook redirect', function() { AuthMock.isAuthenticated.and.returnValue(false); PostProjectMock.getCurrent.and.returnValue({ isReady: function() { return true; }, get: function() { return projectData; } }); $location.search({ facebook_redirect: true }); FacebookMock.checkConnected.and.returnValue($q.when({})); FacebookMock.getUser.and.returnValue($q.when(userData)); UsersMock.check.and.returnValue($q.when({recommended_name: 'chuck'})); var ctrl = createCtrl(); $scope.$digest(); expect(ctrl.state).toBe('facebookSignup'); expect(ctrl.user.username).toBe('chuck'); }); });