gaf-mobile
Version:
GAF mobile Web site
535 lines (423 loc) • 17.5 kB
JavaScript
/* global BudgetListMock */
/* global ProjectMock */
/* global TemplateMock */
/* global UserMock */
describe('Controller: FindPageCtrl', function() {
var ProjectTemplatesMock, CurrenciesMock, BudgetsMock, CookieStoreMock,
TranslationsMock, ProjectsMock, questionsTranslationsDomain,
answersTranslationsDomain;
var createCtrl, loggedInUserMock, jobMock, templateMock, projectMock,
budgetFactoryMock, currencyFactoryMock;
var $scope, $q, $location;
beforeEach(function() {
module('gafMobileApp');
inject(function($rootScope, $controller, _$q_, _$location_) {
$scope = $rootScope.$new();
$q = _$q_;
$location = _$location_;
loggedInUserMock = {
get: function() {
return UserMock();
}
};
jobMock = {
'category': { 'id': 1, },
'id': 3,
'name': 'PHP',
'seo_url': 'php',
'seo_info': {
'phrase_worker': 'PHP Developer',
'plural_phrase_worker': 'PHP Developers',
}
};
templateMock = TemplateMock();
templateMock.dynamic_questions[0].answers = [];
projectMock = jasmine.createSpyObj('currentProject', ['get',
'isReady', 'markAsReady']);
projectMock.get.and.returnValue(ProjectMock());
ProjectsMock = jasmine.createSpyObj('Projects', ['post', 'getCurrent',
'setCurrent', 'projectFactory']);
ProjectsMock.post.and.returnValue($q.when());
ProjectsMock.getCurrent.and.returnValue(projectMock);
TranslationsMock = jasmine.createSpyObj('Translations', [
'getTranslationFromString']);
TranslationsMock.getTranslationFromString.and.returnValue($q.when());
ProjectTemplatesMock = jasmine.createSpyObj('ProjectTemplates', [
'getNextQuestion', 'createDescription']);
CookieStoreMock = jasmine.createSpyObj('CookieStore', ['get']);
currencyFactoryMock = jasmine.createSpyObj('currencyFactoryMock',
['getList', 'getById']);
budgetFactoryMock = jasmine.createSpyObj('budgetFactory', ['getList']);
budgetFactoryMock.getList.and.returnValue(BudgetListMock().budgets);
BudgetsMock = jasmine.createSpyObj('Budgets', ['getWithCurrencies']);
BudgetsMock.getWithCurrencies.and.returnValue($q.when({
budgets: budgetFactoryMock,
currencies: currencyFactoryMock
}));
questionsTranslationsDomain = 'questions/trans/domain';
answersTranslationsDomain = 'answers/trans/domain';
createCtrl = function() {
return $controller('FindPageCtrl', {
loggedInUser: loggedInUserMock,
job: jobMock,
template: templateMock,
ProjectTemplates: ProjectTemplatesMock,
Currencies: CurrenciesMock,
Budgets: BudgetsMock,
CookieStore: CookieStoreMock,
Translations: TranslationsMock,
Projects: ProjectsMock,
$q: $q,
$location: $location,
TEMPLATEQS_TRANSLATION_DOMAIN: questionsTranslationsDomain,
TEMPLATEANS_TRANSLATION_DOMAIN: answersTranslationsDomain
});
};
});
});
describe('Initialization', function() {
describe('when there is a current saved project', function() {
var current;
beforeEach(function() {
current = {
title: 'My Title',
currency: { id: 3 }
};
projectMock.get.and.returnValue(current);
});
it('should set the project to be the current saved project', function() {
ProjectsMock.getCurrent.and.returnValue(projectMock);
var ctrl = createCtrl();
expect(ctrl.project).toEqual(current);
});
it('should post the current saved project if it is ready', function() {
projectMock.isReady.and.returnValue(true);
ProjectsMock.getCurrent.and.returnValue(projectMock);
ProjectsMock.projectFactory.and.returnValue(projectMock);
createCtrl();
expect(ProjectsMock.post).toHaveBeenCalledWith(projectMock);
});
});
describe('when there is no current saved project', function() {
it('should set the project title to the template default', function() {
projectMock.get.and.returnValue({});
ProjectsMock.getCurrent.and.returnValue(projectMock);
var ctrl = createCtrl();
$scope.$digest();
expect(ctrl.project.title).toEqual(templateMock.project_title);
});
});
it('should get the current language set using the cookie', function() {
var language = 'en';
CookieStoreMock.get.and.returnValue(language);
var ctrl = createCtrl();
expect(ctrl.lang).toEqual(language);
});
it('should translate the first dynamic question', function() {
var lang = 'es';
CookieStoreMock.get.and.returnValue(lang);
templateMock.dynamic_questions[0].answers = [];
var questionText = templateMock.dynamic_questions[0]
.project_template_question_text.question_text;
createCtrl();
$scope.$digest();
expect(TranslationsMock.getTranslationFromString)
.toHaveBeenCalledWith(questionText, questionsTranslationsDomain, lang);
});
});
describe('Method: workInstead', function() {
it('should redirect to the signup page if user is logged out', function() {
loggedInUserMock = undefined;
var ctrl = createCtrl();
ctrl.workInstead();
expect($location.url()).toEqual('/signup?role=freelancer');
});
it('should redirect to the jobs page if user is logged in', function() {
loggedInUserMock = UserMock();
var ctrl = createCtrl();
ctrl.workInstead();
expect($location.url()).toEqual('/jobs');
});
});
describe('Method: getAnswerTranslation', function() {
var ctrl;
beforeEach(function() {
ctrl = createCtrl();
// Since this is called upon init of the controller for the translation
// of the first question, let's reset the calls for this spy to correctly
// test the cases below
TranslationsMock.getTranslationFromString.calls.reset();
});
it('should resolve immediately if language is English', function() {
var lang = 'en';
var answer = templateMock.answers[0];
ctrl.getAnswerTranslation(answer, answersTranslationsDomain, lang);
expect(TranslationsMock.getTranslationFromString).not.toHaveBeenCalled();
});
it('should call the Translations service for the translation of the answer',
function() {
var lang = 'fil';
var answer = templateMock.answers[0];
var answerText = answer.answer;
ctrl.getAnswerTranslation(answer, answersTranslationsDomain, lang);
$scope.$digest();
expect(TranslationsMock.getTranslationFromString).toHaveBeenCalledWith(
answerText, answersTranslationsDomain, lang);
});
it('should return the untranslated question if API fails', function() {
var lang = 'fil';
var answer = templateMock.answers[0];
TranslationsMock.getTranslationFromString.and.returnValue($q.reject());
var translated;
ctrl.getAnswerTranslation(answer, answersTranslationsDomain, lang)
.then(function(response) {
translated = response;
});
$scope.$digest();
expect(translated).toEqual(answer);
});
});
describe('Method: getQuestionTranslation', function() {
var ctrl;
beforeEach(function() {
ctrl = createCtrl();
// Since this is called upon init of the controller for the translation
// of the first question, let's reset the calls for this spy to correctly
// test the cases below
TranslationsMock.getTranslationFromString.calls.reset();
});
it('should resolve immediately if language is English', function() {
var lang = 'en';
var question = templateMock.questions['1'];
ctrl.getQuestionTranslation(question, questionsTranslationsDomain, lang);
expect(TranslationsMock.getTranslationFromString).not.toHaveBeenCalled();
});
it('should call the Translations service for the translation of question',
function() {
var lang = 'fil';
var question = templateMock.questions['1'];
var questionText = question.project_template_question_text.question_text;
question.answers = [];
ctrl.getQuestionTranslation(question, questionsTranslationsDomain, lang);
$scope.$digest();
expect(TranslationsMock.getTranslationFromString).toHaveBeenCalledWith(
questionText, questionsTranslationsDomain, lang);
});
it('should get the translation of each of its answers as well', function() {
var lang = 'fil';
var question = templateMock.questions['1'];
var questionText = question.project_template_question_text.question_text;
var answer = templateMock.answers[0];
var answerText = answer.answer;
question.answers = [answer];
ctrl.getQuestionTranslation(question, questionsTranslationsDomain, lang);
$scope.$digest();
expect(TranslationsMock.getTranslationFromString.calls.argsFor(0))
.toEqual([questionText, questionsTranslationsDomain, lang]);
expect(TranslationsMock.getTranslationFromString.calls.argsFor(1))
.toEqual([answerText, answersTranslationsDomain, lang]);
});
it('should return the untranslated question if API fails', function() {
var lang = 'fil';
var question = templateMock.questions['1'];
TranslationsMock.getTranslationFromString.and.returnValue($q.reject());
var translated;
ctrl.getQuestionTranslation(question, questionsTranslationsDomain, lang)
.then(function(response) {
translated = response;
});
$scope.$digest();
expect(translated).toEqual(question);
});
});
describe('Method: electAnswer', function() {
it('should only keep the questions and answers whose question ID is ' +
'less than the current answer\'s question ID', function() {
ProjectTemplatesMock.getNextQuestion.and.returnValue(null);
var ctrl = createCtrl();
// given user has answered 2 questions already
ctrl.questions = [
templateMock.questions['1'],
templateMock.questions['2']
];
ctrl.answers = [
templateMock.answers[0],
templateMock.answers[1]
];
// re-answer first question
ctrl.electAnswer(templateMock.questions['1'], templateMock.answers[0]);
expect(ctrl.questions).toEqual([templateMock.questions['1']]);
expect(ctrl.answers).toEqual([templateMock.answers[0]]);
});
it('should fetch the next translated question', function() {
ProjectTemplatesMock.createDescription.and.returnValue('');
ProjectTemplatesMock.getNextQuestion.and.returnValue(
templateMock.questions['2']);
var question = templateMock.questions['1'];
var answer = templateMock.answers[0];
var ctrl = createCtrl();
spyOn(ctrl, 'getQuestionTranslation').and.returnValue($q.when());
ctrl.electAnswer(question, answer);
$scope.$digest();
expect(ProjectTemplatesMock.getNextQuestion).toHaveBeenCalledWith(
templateMock, question, ctrl.answers);
expect(ctrl.getQuestionTranslation).toHaveBeenCalled();
});
it('should set at most 5 project jobs based on the answer', function() {
var question = templateMock.questions['1'];
var answer = templateMock.answers[0];
var ctrl = createCtrl();
ctrl.electAnswer(question, answer);
expect(ctrl.project.jobs).toEqual(answer.jobs.slice(0, 5));
});
it('should update the project description', function() {
var question = templateMock.questions['1'];
var answer = templateMock.answers[0];
var ctrl = createCtrl();
ctrl.electAnswer(question, answer);
expect(ProjectTemplatesMock.createDescription).toHaveBeenCalledWith(
templateMock, ctrl.answers);
});
});
describe('Method: electFreeformAnswer', function() {
it('should set a formatted freeform answer to the list of answers',
function() {
var question = templateMock.questions['1'];
var freeformAnswer = 'my freeform answer';
var formattedAnswer = {
question_id: question.id,
answer_text: freeformAnswer
};
var ctrl = createCtrl();
spyOn(ctrl, 'electAnswer');
ctrl.electFreeformAnswer(question, freeformAnswer, 0);
expect(ctrl.answers).toEqual([formattedAnswer]);
expect(ctrl.electAnswer).toHaveBeenCalledWith(question, formattedAnswer);
});
it('should accept a blank freeform answer', function() {
var question = templateMock.questions['1'];
var freeformAnswer;
var formattedAnswer = {
question_id: question.id,
answer_text: ''
};
var ctrl = createCtrl();
spyOn(ctrl, 'electAnswer');
ctrl.electFreeformAnswer(question, freeformAnswer, 0);
expect(ctrl.answers).toEqual([formattedAnswer]);
expect(ctrl.electAnswer).toHaveBeenCalledWith(question, formattedAnswer);
});
});
describe('Method: setBudgetsForCurrency', function() {
it('should filter the budgets list depending on currency', function() {
var currencyId = 1;
var budgetList = [
{ currency_id: 1, name: 'budget 1' },
{ currency_id: 1, name: 'budget 2' },
{ currency_id: 2, name: 'budget 3' }
];
budgetFactoryMock.getList.and.returnValue(budgetList);
var ctrl = createCtrl();
$scope.$digest();
ctrl.setBudgetsForCurrency(currencyId);
expect(ctrl.budgetsForCurrency).toEqual([budgetList[0], budgetList[1]]);
});
});
describe('Method: formatBudget', function() {
it('should return the budget range in string form', function() {
var currency = { id: 1, sign: '$' };
var budget = {
minimum: 10,
maximum: 30
};
var ctrl = createCtrl();
var formattedBudget = ctrl.formatBudget(budget, currency);
expect(formattedBudget).toEqual('$10 - $30');
});
it('should return the budget range in string form even if there is no ' +
'maximum budget defined', function() {
var currency = { id: 1, sign: '$' };
var budget = {
minimum: 50
};
var ctrl = createCtrl();
var formattedBudget = ctrl.formatBudget(budget, currency);
expect(formattedBudget).toEqual('$50+');
});
});
describe('Method: postProject', function() {
describe('when the user is logged in', function() {
var project;
beforeEach(function() {
loggedInUserMock = UserMock();
project = ProjectMock();
projectMock.get.and.returnValue(project);
ProjectsMock.projectFactory.and.returnValue(projectMock);
});
it('redirect to the PVP of the new project if successful', function() {
var newProject = angular.extend(project, { id: 1234567 });
ProjectsMock.post.and.returnValue($q.when({
get: function() { return newProject; },
set: jasmine.createSpy()
}));
var ctrl = createCtrl();
ctrl.postProject(project);
$scope.$digest();
expect($location.url()).toEqual('/projects/project-1234567#bids');
});
it('should redirect to the payment verification page if API returned ' +
'that error', function() {
var currentUrl = '/find/skill';
$location.url(currentUrl);
var error = { code: 'UNVERIFIED_PAYMENT' };
ProjectsMock.post.and.returnValue($q.reject(error));
var ctrl = createCtrl();
ctrl.postProject(project);
$scope.$digest();
expect($location.url()).toEqual('/payments/verify' +
'?postProject=true&return=' + encodeURIComponent(currentUrl));
});
it('should set the error variable to be negative balance', function() {
var error = { code: 'NEGATIVE_BALANCE' };
ProjectsMock.post.and.returnValue($q.reject(error));
var ctrl = createCtrl();
ctrl.postProject(project);
$scope.$digest();
expect(ctrl.error.negativeBalance).toBeTruthy();
});
it('should set the error variable to internal error for others',
function() {
var error = { code: 'SOME_OTHER_ERROR' };
ProjectsMock.post.and.returnValue($q.reject(error));
var ctrl = createCtrl();
ctrl.postProject(project);
$scope.$digest();
expect(ctrl.error.internalError).toBeTruthy();
});
});
describe('when the user is logged out', function() {
var project, currentUrl;
beforeEach(function() {
loggedInUserMock = undefined;
project = ProjectMock();
projectMock.get.and.returnValue(project);
ProjectsMock.projectFactory.and.returnValue(projectMock);
currentUrl = '/find/skill';
$location.url(currentUrl);
var ctrl = createCtrl();
ctrl.postProject(project);
});
it('should save the project as the current', function() {
expect(ProjectsMock.setCurrent).toHaveBeenCalledWith(projectMock);
});
it('should mark the project as ready', function() {
expect(projectMock.markAsReady).toHaveBeenCalledWith(true);
});
it('should redirect to the signup page', function() {
expect($location.url()).toEqual('/signup?role=employer&return=' +
encodeURIComponent(currentUrl));
});
});
});
});
;