gaf-mobile
Version:
GAF mobile Web site
397 lines (330 loc) • 13 kB
JavaScript
'use strict';
/* global ProjectMock */
/* global UserMock */
/* global BudgetListMock */
/* global FixedHiremeMock */
/* global HourlyHiremeMock */
describe('Service: Hireme', function() {
var ProjectsMock, AnalyticsMock, BudgetsMock, MAX_HIREME_BUDGETS_MOCK,
DEFAULT_PROJECT_CONFIG_MOCK;
var user, currency;
var Hireme, $q, $scope, $rootScope;
beforeEach(module('gafMobileApp', function($provide) {
AnalyticsMock = jasmine.createSpyObj('Analytics', ['trackAction',
'trackError', 'trackABTest', 'trackMobileUserTiming',
'trackGTMConversion']);
ProjectsMock = jasmine.createSpyObj('Projects', ['post']);
BudgetsMock = jasmine.createSpyObj('Budgets', ['getWithCurrencies']);
MAX_HIREME_BUDGETS_MOCK = {
'USD': 20000,
'PHP': 900000
};
DEFAULT_PROJECT_CONFIG_MOCK = {
'type': 'fixed',
'hourlyDuration': 'one_to_four_weeks',
'hourlyCommitment': 10,
'hourlyInterval': 'week'
};
$provide.value('Analytics', AnalyticsMock);
$provide.value('Projects', ProjectsMock);
$provide.value('Budgets', BudgetsMock);
$provide.value('MAX_HIREME_BUDGETS', MAX_HIREME_BUDGETS_MOCK);
$provide.value('DEFAULT_PROJECT_CONFIG', DEFAULT_PROJECT_CONFIG_MOCK);
}));
beforeEach(inject(function(_Hireme_, _$q_, _$rootScope_) {
Hireme = _Hireme_;
$q = _$q_;
$rootScope = _$rootScope_;
$scope = $rootScope.$new();
user = UserMock();
user.jobs = [1, 2, 3, 4, 5, 6];
currency = { code: 'USD', sign: '$', exchange_rate: 2, id: 1 };
}));
describe('Method: getCurrencies', function() {
it('should return the list of currencies', function() {
var mockResult = BudgetListMock();
BudgetsMock.getWithCurrencies.and.returnValue($q.when(mockResult));
var currencies;
Hireme.getCurrencies().then(function(result) {
currencies = result;
});
$scope.$digest();
expect(currencies).toBe(mockResult.currencies);
});
it('should return an empty array if there is an error in fetching the ' +
'budgets with currencies', function() {
BudgetsMock.getWithCurrencies.and.returnValue($q.reject());
var currencies;
Hireme.getCurrencies().then(function(result) {
currencies = result.getList();
});
$scope.$digest();
expect(currencies).toEqual([]);
});
});
describe('Method: getDefaultValues', function() {
it('should return default values for fixed hireme project by default',
function() {
expect(Hireme.getDefaultValues(user, currency)).toEqual({
user: user,
days: 3,
title: 'Project for ' + user.username,
hireme: true,
currency: currency,
description: 'Hi '+ user.username +', I noticed your profile and ' +
'would like to offer you my project. We can discuss any details ' +
'over chat.',
type: 'fixed'
});
});
it('should return default values for hireme project given the type',
function() {
expect(Hireme.getDefaultValues(user, currency, 'fixed')).toEqual({
user: user,
days: 3,
title: 'Project for ' + user.username,
hireme: true,
currency: currency,
description: 'Hi '+ user.username +', I noticed your profile and ' +
'would like to offer you my project. We can discuss any details ' +
'over chat.',
type: 'fixed'
});
expect(Hireme.getDefaultValues(user, currency, 'hourly')).toEqual({
user: user,
title: 'Project for ' + user.username,
hireme: true,
currency: currency,
description: 'Hi '+ user.username +', I noticed your profile and ' +
'would like to offer you my project. We can discuss any details ' +
'over chat.',
type: 'hourly',
hourly_project_info: {
duration_enum: 'one_to_four_weeks',
commitment: {
hours: 10,
interval: 'week'
}
}
});
});
});
describe('Method: minimumBudget', function() {
var budgetListFactoryMock;
beforeEach(function() {
budgetListFactoryMock = jasmine.createSpyObj('budgetListFactory',
['getByIndex']);
budgetListFactoryMock.getByIndex.and.callFake(function(index, params) {
if (params.project_type === 'fixed') {
return { minimum: 10 };
} else if (params.project_type === 'hourly') {
return { minimum: 2 };
}
});
});
it('should return the minimum budget for fixed hireme projects by default',
function() {
BudgetsMock.getWithCurrencies.and.returnValue($q.when({
budgets: budgetListFactoryMock
}));
var minimumBudget;
Hireme.minimumBudget(currency).then(function(minimum) {
minimumBudget = minimum;
});
$scope.$digest();
expect(minimumBudget).toBe(10);
});
it('should return the minimum budget for the given project type parameter',
function() {
BudgetsMock.getWithCurrencies.and.returnValue($q.when({
budgets: budgetListFactoryMock
}));
var minimumBudget;
Hireme.minimumBudget(currency, 'fixed').then(function(minimum) {
minimumBudget = minimum;
});
$scope.$digest();
expect(minimumBudget).toBe(10);
Hireme.minimumBudget(currency, 'hourly').then(function(minimum) {
minimumBudget = minimum;
});
$scope.$digest();
expect(minimumBudget).toBe(2);
});
it('should return equivalent of $10 USD if there is an error when ' +
'getting the budgets list', function() {
BudgetsMock.getWithCurrencies.and.returnValue($q.reject());
var minimumBudget;
Hireme.minimumBudget(currency).then(function(minimum) {
minimumBudget = minimum;
});
$scope.$digest();
expect(minimumBudget).toBe(5);
});
});
describe('Method: maximumBudget', function() {
it('should return the maximum value from the MAX_HIREME_BUDGETS constant' +
'based on currency', function() {
var maximumBudget;
currency = { code: 'USD' };
Hireme.maximumBudget(currency).then(function(maximum) {
maximumBudget = maximum;
});
$scope.$digest();
expect(maximumBudget).toBe(20000);
currency = { code: 'PHP' };
Hireme.maximumBudget(currency).then(function(maximum) {
maximumBudget = maximum;
});
$scope.$digest();
expect(maximumBudget).toBe(900000);
});
});
describe('Method: createForUser', function() {
it('should create a new fixed hireme project', function() {
var project = ProjectMock();
ProjectsMock.post.and.returnValue($q.when({
get: function() { return project; }
}));
var expectedProjectToCreate = FixedHiremeMock();
Hireme.createForUser(user, 100, currency, 'title', {
description: 'description',
days: 1,
type: 'fixed'
});
$scope.$digest();
var actualProjectToCreate = ProjectsMock.post.calls.argsFor(0)[0].get();
expect(actualProjectToCreate).toEqual(expectedProjectToCreate);
expect(AnalyticsMock.trackAction)
.toHaveBeenCalledWith('project', 'post', 'SUCCESS');
expect(AnalyticsMock.trackGTMConversion)
.toHaveBeenCalledWith('project', project.id, 'MBW HireMe Posted');
});
it('should create a new hourly hireme project', function() {
ProjectsMock.post.and.returnValue($q.when({
get: function() { return ProjectMock(); }
}));
var expectedProjectToCreate = HourlyHiremeMock();
Hireme.createForUser(user, 100, currency, 'title', {
description: 'description',
type: 'hourly',
hourly_project_info: {
duration_enum: 'duration_enum',
commitment: {
hours: 20,
interval: 'week'
}
}
});
$scope.$digest();
var actualProjectToCreate = ProjectsMock.post.calls.argsFor(0)[0].get();
expect(actualProjectToCreate).toEqual(expectedProjectToCreate);
expect(AnalyticsMock.trackAction)
.toHaveBeenCalledWith('project', 'post', 'SUCCESS');
});
it('should create a new hireme project with default values', function() {
ProjectsMock.post.and.returnValue($q.when({
get: function() { return ProjectMock(); }
}));
var project = Hireme.createForUser(user, 100, currency, 'title');
$scope.$digest();
expect(project.$$state.status).toBe(1); // promise resolved
expect(ProjectsMock.post).toHaveBeenCalled();
expect(AnalyticsMock.trackAction).toHaveBeenCalledWith('project', 'post',
'SUCCESS');
});
it('should catch a duplicate project error', function() {
ProjectsMock.post.and.returnValue($q.reject({
code: 'HIREME_DUPLICATE_PROJECT_TITLE', data: 'data'
}));
var project = Hireme.createForUser(user, 100, currency, 'title');
$scope.$digest();
expect(project.$$state.status).toBe(2); // promise rejected
expect(ProjectsMock.post).toHaveBeenCalled();
expect(AnalyticsMock.trackError).toHaveBeenCalledWith(
'project', 'post', 'HIREME_DUPLICATE_PROJECT_TITLE', 'data');
});
it('should catch an unverified payment error', function() {
ProjectsMock.post.and.returnValue($q.reject({
code: 'UNVERIFIED_PAYMENT', data: 'data'
}));
var project = Hireme.createForUser(user, 100, currency, 'title');
$scope.$digest();
expect(project.$$state.status).toBe(2); // promise rejected
expect(ProjectsMock.post).toHaveBeenCalled();
expect(AnalyticsMock.trackError).toHaveBeenCalledWith(
'project', 'post', 'UNVERIFIED_PAYMENT', 'data');
});
it('should catch a negative balance error', function() {
ProjectsMock.post.and.returnValue($q.reject({
code: 'NEGATIVE_BALANCE', data: 'data'
}));
var project = Hireme.createForUser(user, 100, currency, 'title');
$scope.$digest();
expect(project.$$state.status).toBe(2); // promise rejected
expect(ProjectsMock.post).toHaveBeenCalled();
expect(AnalyticsMock.trackError).toHaveBeenCalledWith(
'project', 'post', 'NEGATIVE_BALANCE', 'data');
});
it('should catch a gaf exception', function() {
ProjectsMock.post.and.returnValue($q.reject({
code: 'GAF_EXCEPTION', data: 'data'
}));
var project = Hireme.createForUser(user, 100, currency, 'title');
$scope.$digest();
expect(project.$$state.status).toBe(2); // promise rejected
expect(ProjectsMock.post).toHaveBeenCalled();
expect(AnalyticsMock.trackError).toHaveBeenCalledWith(
'project', 'post', 'GAF_EXCEPTION', 'data');
});
it('should catch a budget too large', function() {
ProjectsMock.post.and.returnValue($q.reject({
code: 'HIREME_BID_AMOUNT_TOO_BIG', data: 'data'
}));
var project = Hireme.createForUser(user, 100, currency, 'title');
$scope.$digest();
expect(project.$$state.status).toBe(2); // promise rejected
expect(ProjectsMock.post).toHaveBeenCalled();
expect(AnalyticsMock.trackError).toHaveBeenCalledWith(
'project', 'post', 'HIREME_BID_AMOUNT_TOO_BIG', 'data');
});
it('should catch a budget too small', function() {
ProjectsMock.post.and.returnValue($q.reject({
code: 'HIREME_BID_AMOUNT_TOO_SMALL', data: 'data'
}));
var project = Hireme.createForUser(user, 100, currency, 'title');
$scope.$digest();
expect(project.$$state.status).toBe(2); // promise rejected
expect(ProjectsMock.post).toHaveBeenCalled();
expect(AnalyticsMock.trackError).toHaveBeenCalledWith(
'project', 'post', 'HIREME_BID_AMOUNT_TOO_SMALL', 'data');
});
it('should catch an error if hired freelancer' +
'has no skills', function() {
ProjectsMock.post.and.returnValue($q.reject({
code: 'HIREME_PROJECT_NO_JOBS', data: 'data'
}));
var hiremeError;
Hireme.createForUser(user, 100, currency, 'title')
.catch(function(error) {
hiremeError = error;
});
$scope.$digest();
expect(hiremeError.hasNoSkills).toBeTruthy();
expect(ProjectsMock.post).toHaveBeenCalled();
expect(AnalyticsMock.trackError).toHaveBeenCalledWith(
'project', 'post', 'HIREME_PROJECT_NO_JOBS', 'data');
});
it('should catch an unknown error', function() {
ProjectsMock.post.and.returnValue($q.reject({
code: 'UNKNOWN', data: 'data'
}));
var project = Hireme.createForUser(user, 100, currency, 'title');
$scope.$digest();
expect(project.$$state.status).toBe(2); // promise rejected
expect(ProjectsMock.post).toHaveBeenCalled();
expect(AnalyticsMock.trackError).toHaveBeenCalledWith(
'project', 'post', 'UNKNOWN', 'data');
});
});
});