UNPKG

gaf-mobile

Version:

GAF mobile Web site

482 lines (394 loc) 15.5 kB
'use strict'; /* global FixedHiremeMock */ /* global HourlyHiremeMock */ describe('Component: Hireme Modal', function() { var $scope, $compile, $q; var defaultFixedValues, defaultHourlyValues, currenciesMock, userMock, currencyMock; function compileDirective(html) { var element, compiledElement; html = html || '<hireme-modal ' + 'user="{ id: 1, username: \'hiremefreelancer\' }"' + 'currency="{ code: \'USD\', sign: \'$\', exchange_rate: null, id: 1 }"' + 'close="function"' + '></hireme-modal>'; element = angular.element(html); compiledElement = $compile(element)($scope); $scope.$digest(); return compiledElement; } beforeEach(module('gafMobileApp')); beforeEach(module('components/hireme-modal/hireme-modal.html')); beforeEach(inject(function($rootScope, _$compile_, $templateCache, Hireme, _$q_) { $templateCache.put('/views/main.html', ''); $scope = $rootScope.$new(); $compile = _$compile_; $q = _$q_; userMock = { id: 1, username: 'hiremefreelancer' }; currencyMock = { code: 'USD', sign: '$', exchange_rate: 2, id: 1 }; defaultHourlyValues = HourlyHiremeMock(); defaultFixedValues = FixedHiremeMock(); defaultFixedValues.days = 3; currenciesMock = { getList: function() { return [ { id: 1, code: 'USD', sign: '$' }, { id: 2, code: 'PHP', sign: 'P' }, ]; } }; spyOn(Hireme, 'getCurrencies').and.returnValue($q.when(currenciesMock)); spyOn(Hireme, 'getDefaultValues').and.callFake(function(u, c, projectType) { if (projectType === 'hourly') { return defaultHourlyValues; } else { return defaultFixedValues; } }); spyOn(Hireme, 'minimumBudget').and.callFake(function(currency, type) { if (currency.code === 'USD' && (type === 'fixed' || !type)) { return $q.when(10); } else if (currency.code === 'USD' && type === 'hourly') { return $q.when(2); } else if (currency.code === 'PHP' && (type === 'fixed' || !type)) { return $q.when(500); } else if (currency.code === 'PHP' && type === 'hourly') { return $q.when(100); } }); spyOn(Hireme, 'maximumBudget').and.callFake(function(currency) { if (currency.code === 'USD') { return $q.when(20); } else if (currency.code === 'PHP') { return $q.when(1000); } }); })); describe('Initialization', function() { var controller; beforeEach(function() { var modal = compileDirective(); controller = modal.controller('hiremeModal'); }); it('should set the defaults for the currencies, hireme project, ' + 'minimum budget, and maximum budget', function() { expect(controller.currencies).toEqual(currenciesMock.getList()); expect(controller.minimumBudget).toEqual(10); expect(controller.maximumBudget).toEqual(20); expect(controller.hiremeProject).toEqual(defaultFixedValues); }); }); describe('Creating the hireme project after deposit success', function() { var controller, currentProject; beforeEach(inject(function(Projects, Hireme) { currentProject = { user: userMock, currency: currencyMock, type: 'fixed', hireme: true }; spyOn(Hireme, 'createForUser').and.returnValue($q.when({})); spyOn(Projects, 'getCurrent').and.returnValue({ get: function() { return currentProject; } }); controller = compileDirective().isolateScope().ctrl; })); it('should set the hireme project then proceed to creating it', function() { expect(controller.hiremeProject).toEqual(currentProject); }); }); describe('Hireme Modal form', function() { var modal, isolateScope, form, controller; beforeEach(function() { // TODO: Cleanup AB test for creating Hourly Hireme projects inject(function(Experiments) { spyOn(Experiments, 'activateTest').and.returnValue(true); }); modal = compileDirective(); isolateScope = modal.isolateScope(); controller = isolateScope.ctrl; form = isolateScope.hiremeForm; }); describe('Form field for project type', function() { it('should initially be set to fixed', function() { expect(controller.hiremeProject.type) .toEqual('fixed'); }); }); describe('Form field for currency', function() { it('should initially be the currency of employer', function() { expect(form.currency.$valid).toBeTruthy(); expect(form.currency.$viewValue).toEqual(currencyMock); }); it('should call the controller function for currency change', function() { var newCurrency = { id: 2, code: 'PHP', sign: 'P' }; spyOn(isolateScope.ctrl, 'onCurrencyChange'); form.currency.$setViewValue(newCurrency); angular.element(modal.find('select')).triggerHandler('change'); expect(isolateScope.ctrl.onCurrencyChange) .toHaveBeenCalledWith(newCurrency); }); }); describe('Form field for budget', function() { it('should initially be the default minimum budget wrt to currency of ' + 'employer', function() { expect(form.budget.$viewValue).toEqual('10'); // string in form expect(form.budget.$valid).toBeTruthy(); }); it('should be valid if minimum <= amount <= maximum', function() { form.budget.$setViewValue('10'); expect(form.budget.$valid).toBeTruthy(); form.budget.$setViewValue('11'); expect(form.budget.$valid).toBeTruthy(); form.budget.$setViewValue('20'); expect(form.budget.$valid).toBeTruthy(); }); it('should be invalid if amount < minimum', function() { form.budget.$setViewValue('9'); expect(form.budget.$valid).toBeFalsy(); expect(form.budget.$error.min).toBeTruthy(); }); it('should be invalid if amount > maximum', function() { form.budget.$setViewValue('21'); expect(form.budget.$valid).toBeFalsy(); expect(form.budget.$error.max).toBeTruthy(); }); it('should be invalid if amount is not a number', function() { form.budget.$setViewValue('abc'); expect(form.budget.$valid).toBeFalsy(); expect(form.budget.$error.number).toBeTruthy(); }); it('should be invalid if amount does not have a value', function() { form.budget.$setViewValue(); expect(form.budget.$valid).toBeFalsy(); expect(form.budget.$error.required).toBeTruthy(); }); }); describe('Form field for days', function() { it('should initially be the default days', function() { expect(form.days.$viewValue).toEqual('3'); // string in form expect(form.days.$valid).toBeTruthy(); }); it('should be valid if 1 <= days <= 1000', function() { form.days.$setViewValue('1'); expect(form.days.$valid).toBeTruthy(); form.days.$setViewValue('2'); expect(form.days.$valid).toBeTruthy(); form.days.$setViewValue('1000'); expect(form.days.$valid).toBeTruthy(); }); it('should be invalid if days < 1', function() { form.days.$setViewValue('0'); expect(form.days.$valid).toBeFalsy(); expect(form.days.$error.min).toBeTruthy(); }); it('should be invalid if days > 1000', function() { form.days.$setViewValue('1001'); expect(form.days.$valid).toBeFalsy(); expect(form.days.$error.max).toBeTruthy(); }); it('should be invalid if days is not a number', function() { form.days.$setViewValue('abc'); expect(form.days.$valid).toBeFalsy(); expect(form.days.$error.number).toBeTruthy(); }); it('should be invalid if days does not have a value', function() { form.days.$setViewValue(); expect(form.days.$valid).toBeFalsy(); expect(form.days.$error.required).toBeTruthy(); }); it('should be hidden if project type is set to hourly', function() { controller.hiremeProject.type = 'hourly'; isolateScope.$digest(); expect(form.days).not.toBeDefined(); expect(form.$valid).toBeTruthy(); }); }); describe('Form submit button', function() { var submitBtn; beforeEach(function() { submitBtn = modal.find('button'); }); it('should be enabled if form is valid', function() { expect(submitBtn.attr('disabled')).toBeFalsy(); }); it('should be disabled if form is invalid', function() { form.$setValidity('hiremeForm.budget.$error.min', false); $scope.$digest(); expect(submitBtn.attr('disabled')).toBeTruthy(); }); it('should call the hireMe() function of the controller', function() { spyOn(isolateScope.ctrl, 'hireMe'); angular.element(modal.find('form')).triggerHandler('submit'); expect(isolateScope.ctrl.hireMe).toHaveBeenCalled(); }); }); describe('Modal close button', function() { var closeBtn; beforeEach(function() { closeBtn = modal.find('a'); }); it('should call the closeModal() on controller when clicked', function() { spyOn(isolateScope.ctrl, 'close'); angular.element(closeBtn).triggerHandler('click'); expect(isolateScope.ctrl.close).toHaveBeenCalled(); }); }); }); describe('Changing the project type', function() { var controller, newType; beforeEach(function() { var modal = compileDirective(); controller = modal.controller('hiremeModal'); newType = 'hourly'; }); it('should refresh the minimum budget', function() { expect(controller.minimumBudget).toEqual(10); controller.onTypeChange(newType); $scope.$digest(); expect(controller.minimumBudget).toEqual(2); }); it('should remove the `hourly_project_info` property and add the `days`' + 'property with default value when set to fixed', function() { controller.onTypeChange('fixed'); expect(controller.hiremeProject.hourly_project_info).not.toBeDefined(); expect(controller.hiremeProject.days).toEqual(defaultFixedValues.days); }); it('should remove the `days` property and add the `hourly_project_info`' + 'property with default values when set to hourly', function() { controller.onTypeChange('hourly'); expect(controller.hiremeProject.days).not.toBeDefined(); expect(controller.hiremeProject.hourly_project_info) .toEqual(defaultHourlyValues.hourly_project_info); }); }); describe('Changing the currency', function() { var controller, newCurrency; beforeEach(function() { var modal = compileDirective(); controller = modal.controller('hiremeModal'); newCurrency = { id: 2, code: 'PHP', sign: 'P' }; }); it('should refresh the budget range', function() { expect(controller.minimumBudget).toEqual(10); expect(controller.maximumBudget).toEqual(20); controller.onCurrencyChange(newCurrency); $scope.$digest(); expect(controller.minimumBudget).toEqual(500); expect(controller.maximumBudget).toEqual(1000); }); }); describe('Submitting a valid form', function() { var Projects, controller, newProject; beforeEach(function() { var modal = compileDirective(); controller = modal.controller('hiremeModal'); }); describe('for creating a fixed hireme project', function() { beforeEach(inject(function(_Projects_, Hireme) { Projects = _Projects_; newProject = { get: function() { return { id: 123 }; } }; spyOn(Projects, 'setCurrent'); spyOn(Hireme, 'createForUser').and.returnValue($q.when(newProject)); spyOn(controller, 'close'); controller.hiremeProject.type = 'fixed'; controller.hireMe(); $scope.$digest(); })); describe('when the hireme project was posted successfully', function() { it('should set the project as current and close the modal', function() { expect(Projects.setCurrent).toHaveBeenCalledWith(newProject); expect(controller.close).toHaveBeenCalled(); }); }); }); describe('for creating an hourly hireme project', function() { describe('if employer has verified payment sources', function() { var $location, projectId; beforeEach(inject(function(Deposits, Hireme, _$location_) { $location = _$location_; projectId = 999; newProject = { get: function() { return { id: projectId, hireme_initial_bid: { bidder_id: userMock.id } }; } }; spyOn($location, 'url'); spyOn(Hireme, 'createForUser').and.returnValue($q.when(newProject)); spyOn(Deposits, 'getVerifiedPaymentSources').and.returnValue( $q.when({ 'payment_source': [1, 2, 3] })); controller.hiremeProject.type = 'hourly'; controller.hireMe(); $scope.$digest(); })); it('should create the project then redirect to the ' + 'PVP\'s management tab', function() { expect($location.url).toHaveBeenCalledWith( '/projects/project-' + projectId + '?createMilestoneFor=' + userMock.id + '#management'); }); }); }); describe('when the hireme project was posted unsuccessfully', function() { var Hireme, modal, controller, error; describe('due to duplicate title', function() { beforeEach(inject(function(_Hireme_) { Hireme = _Hireme_; error = { code: 'DUPLICATE_TITLE', hiremeDuplicateTitle: true }; spyOn(Hireme, 'createForUser').and.returnValues( $q.reject(error), $q.reject(error), $q.when() ); modal = compileDirective(); controller = modal.controller('hiremeModal'); controller.hireMe(); $scope.$digest(); })); it('should increment the title then retry until success', function() { expect(Hireme.createForUser.calls.count()).toEqual(3); expect(Hireme.createForUser.calls.argsFor(1)).toEqual([ userMock, 10, currencyMock, 'title -- 2', { days: 3, type: 'fixed' } ]); expect(Hireme.createForUser.calls.argsFor(2)).toEqual([ userMock, 10, currencyMock, 'title -- 3', { days: 3, type: 'fixed' } ]); }); }); describe('due to a reason other than duplicate title', function() { var Hireme; beforeEach(inject(function(_Hireme_) { Hireme = _Hireme_; error = { code: 'INTERNAL_ERROR', internalError: true }; spyOn(Hireme, 'createForUser').and.returnValue($q.reject(error)); modal = compileDirective(); controller = modal.controller('hiremeModal'); controller.hireMe(); $scope.$digest(); })); it('should store the error', function() { expect(Hireme.createForUser.calls.count()).toEqual(1); expect(controller.error).toEqual(error); }); }); }); }); });