const $ = require('jquery'); const _ = require('underscore'); const Backbone = require('backbone'); const ProfileFormView = require('dashboard/views/profile/profile-form/profile-form-view'); const PasswordValidatedForm = require('dashboard/helpers/password-validated-form'); const ModalsServiceModel = require('builder/components/modals/modals-service-model'); const UserModel = require('dashboard/data/user-model'); const modals = new ModalsServiceModel(); const DISPLAY_EMAIL = 'admin@carto.com'; const DESCRIPTION = 'description'; const AVATAR_URL = 'avatar_url'; const NAME = 'name'; const LAST_NAME = 'last_name'; const EMAIL = 'pepe@carto.com'; const COMPANY = 'CARTO'; const JOB_ROLE = 'Developer'; const INDUSTRY = 'GIS and Mapping'; const COMPANY_EMPLOYEES = '1-5'; const USE_CASE = 'Data Monetization'; const PHONE = '+34666666666'; const WEBSITE = 'website'; const TWITTER_USERNAME = 'twitter_username'; const DISQUS_SHORTNAME = 'disqus_shortname'; const AVAILABLE_FOR_HIRE = true; const LOCATION = 'location'; const PASSWORD = 'password'; const MALICIOUS_TEXT = '/>'; const ESCAPED_TEXT = '/><script>alert("wadus");</script>'; const ESCAPED_TEXT_MAX = '/><script>alert('; describe('dashboard/views/profile/profile-form/profile-form-view', function () { let userModel, model, configModel, view, setLoadingSpy, showSuccessSpy, showErrorsSpy; const createViewFn = function (options) { userModel = new UserModel( _.extend({ username: 'pepe', base_url: 'http://pepe.carto.com', email: EMAIL, account_type: 'FREE', job_role: JOB_ROLE, industry: INDUSTRY, company_employees: COMPANY_EMPLOYEES, use_case: USE_CASE, company: COMPANY, phone: PHONE, description: DESCRIPTION, avatar_url: AVATAR_URL, name: NAME, last_name: LAST_NAME, website: WEBSITE, twitter_username: TWITTER_USERNAME, disqus_shortname: DISQUS_SHORTNAME, available_for_hire: AVAILABLE_FOR_HIRE, location: LOCATION, viewer: false, needs_password_confirmation: true }, options) ); setLoadingSpy = jasmine.createSpy('setLoading'); showSuccessSpy = jasmine.createSpy('showSuccess'); showErrorsSpy = jasmine.createSpy('showErrors'); model = new Backbone.Model(); configModel = new Backbone.Model({ avatar_valid_extensions: ['jpeg', 'jpg', 'gif', 'png'] }); configModel.prefixUrl = () => ''; const view = new ProfileFormView({ userModel, configModel, setLoading: setLoadingSpy, onSaved: showSuccessSpy, onError: showErrorsSpy, renderModel: model, modals }); return view; }; beforeEach(function () { spyOn(PasswordValidatedForm, 'showPasswordModal').and.callFake( function (options) { options.onPasswordTyped && options.onPasswordTyped(PASSWORD); } ); view = createViewFn(); }); describe('.render', function () { it('should render properly', function () { view.render(); expect(view.$el.html()).toContain('
'); expect(view.$el.html()).toContain('
'); expect(view.$el.html()).toContain(``); expect(view.$el.html()).toContain(``); expect(view.$el.html()).toContain(``); expect(view.$el.html()).toContain(``); expect(view.$el.html()).toContain(``); expect(view.$el.html()).toContain(``); expect(view.$el.html()).toContain(``); expect(view.$el.html()).toContain(``); expect(view.$el.html()).toContain(``); expect(view.$el.html()).toContain(``); expect(view.$el.html()).toContain(` `); expect(view.$el.html()).toContain('profile.views.form.builder'); expect(view.$el.html()).toContain('profile.views.form.write_access'); expect(view.$el.html()).toContain(``); // Industry const industryDropdown = view.$('#user_industry'); expect(industryDropdown.find('option').length).toBe(21); expect(industryDropdown.find('option:checked').text()).toContain(INDUSTRY); }); it('should render the company employees dropdown', function () { view.render(); const companyEmployeesDropdown = view.$('#user_company_employees'); expect(companyEmployeesDropdown.find('option').length).toBe(8); expect(companyEmployeesDropdown.find('option:checked').text()).toContain(COMPANY_EMPLOYEES); }); it('should render the use case dropdown', function () { view.render(); const useCaseDropdown = view.$('#user_use_case'); expect(useCaseDropdown.find('option').length).toBe(16); expect(useCaseDropdown.find('option:checked').text()).toContain(USE_CASE); }); }); describe('escape inputs', function () { beforeEach(function () { view = createViewFn({ name: MALICIOUS_TEXT, last_name: MALICIOUS_TEXT, email: MALICIOUS_TEXT, job_role: MALICIOUS_TEXT, company: MALICIOUS_TEXT, phone: MALICIOUS_TEXT, description: MALICIOUS_TEXT, avatar_url: MALICIOUS_TEXT, website: MALICIOUS_TEXT, twitter_username: MALICIOUS_TEXT, disqus_shortname: MALICIOUS_TEXT }); }); it('should escape the inputs when saving', function () { const event = $.Event('click'); spyOn(view._userModel, 'save'); view.render(); view._onClickSave(event); const newUser = { description: ESCAPED_TEXT, avatar_url: ESCAPED_TEXT, name: ESCAPED_TEXT_MAX, last_name: ESCAPED_TEXT_MAX, email: ESCAPED_TEXT_MAX, company: ESCAPED_TEXT_MAX, phone: ESCAPED_TEXT_MAX, job_role: ESCAPED_TEXT_MAX, website: ESCAPED_TEXT_MAX, twitter_username: ESCAPED_TEXT_MAX, disqus_shortname: ESCAPED_TEXT_MAX }; expect(view._userModel.save).toHaveBeenCalledWith( newUser, { wait: true, url: '/api/v3/me', success: showSuccessSpy, error: showErrorsSpy, attrs: { user: _.extend({ password_confirmation: PASSWORD }, newUser) } } ); }); }); describe('errors', function () { describe('email', function () { describe('.render', function () { it('should render properly', function () { view._renderModel.set('errors', { email: ['error'] }); view.render(); expect(view.$el.html()).toContain(''); }); }); }); }); describe('is viewer', function () { beforeEach(function () { userModel.set('viewer', true); }); describe('.render', function () { it('should render properly', function () { view.render(); expect(view.$el.html()).toContain('profile.views.form.viewer'); expect(view.$el.html()).toContain('profile.views.form.read_only'); }); }); }); describe('is inside org', function () { beforeEach(function () { spyOn(userModel, 'isInsideOrg').and.returnValue(true); }); describe('.render', function () { it('should render properly', function () { spyOn(userModel, 'isViewer').and.returnValue(true); spyOn(view, '_getOrgAdminEmail').and.returnValue(DISPLAY_EMAIL); view.render(); expect(view.$el.html()).toContain(`profile.views.form.become_builder`); }); }); describe('._getOrgAdminEmail', function () { it('should get org admin email', function () { userModel.organization = { display_email: DISPLAY_EMAIL }; expect(view._getOrgAdminEmail()).toBe(DISPLAY_EMAIL); }); }); }); describe('can change email', function () { beforeEach(function () { userModel.set('can_change_email', true); }); describe('.render', function () { it('should render properly', function () { view.render(); expect(view.$el.html()).toContain(''); }); }); }); describe('._getOrgAdminEmail', function () { it('should return null', function () { expect(view._getOrgAdminEmail()).toBeNull(); }); }); describe('._initModels', function () { it('should init models', function () { expect(view._userModel).toBe(userModel); expect(view._configModel).toBe(configModel); expect(view._renderModel).toEqual(model); }); }); describe('._initViews', function () { it('should init views', function () { view.render(); expect(_.size(view._subviews)).toBe(1); }); it('should support previous job role values', function () { view = createViewFn({ job_role: 'unexpected value' }); view.render(); expect(view.$('#user_job_role').val()).toEqual('unexpected value'); }); it('should support previous industry values', function () { view = createViewFn({ industry: 'unexpected value' }); view.render(); expect(view.$('#user_industry').text()).toContain('unexpected value'); }); }); describe('._getUserFields', function () { it('should get user fields', function () { expect(view._getUserFields()).toEqual({ description: DESCRIPTION, avatar_url: AVATAR_URL, name: NAME, last_name: LAST_NAME, email: EMAIL, company: COMPANY, phone: PHONE, job_role: JOB_ROLE, industry: INDUSTRY, company_employees: COMPANY_EMPLOYEES, use_case: USE_CASE, website: WEBSITE, twitter_username: TWITTER_USERNAME, disqus_shortname: DISQUS_SHORTNAME, available_for_hire: AVAILABLE_FOR_HIRE, location: LOCATION }); }); }); describe('._getDestinationValues', function () { const destDescription = '_description'; const destAvatarUrl = '_avatar'; const destName = '_name'; const destLastName = '_last_name'; const destEmail = '_email'; const destCompany = '_company'; const destPhone = '_phone'; const destJobRole = 'Developer'; const destIndustry = 'GIS and Mapping'; const destCompanyEmployees = '1-5'; const destUseCase = 'Data Monetization'; const destWebsite = '_website'; const destTwitterUsername = '_twitter_username'; const destDisqusShortname = '_disqus_shortname'; const destAvailableForHire = false; const destLocation = '_location'; it('should get destination values', function () { view = createViewFn({ description: destDescription, avatar_url: destAvatarUrl, name: destName, last_name: destLastName, email: destEmail, company: destCompany, phone: destPhone, job_role: destJobRole, industry: destIndustry, company_employees: destCompanyEmployees, use_case: destUseCase, website: destWebsite, twitter_username: destTwitterUsername, disqus_shortname: destDisqusShortname, available_for_hire: destAvailableForHire, location: destLocation }); view.render(); expect(view._getDestinationValues()).toEqual({ description: destDescription, avatar_url: destAvatarUrl, name: destName, last_name: destLastName, email: destEmail, company: destCompany, phone: destPhone, job_role: destJobRole, industry: destIndustry, company_employees: destCompanyEmployees, use_case: destUseCase, website: destWebsite, twitter_username: destTwitterUsername, disqus_shortname: destDisqusShortname, available_for_hire: destAvailableForHire, location: destLocation }); }); }); describe('._onClickSave', function () { it('should require password confirmation if needed', function () { view._onClickSave(); expect(PasswordValidatedForm.showPasswordModal).toHaveBeenCalled(); }); it('should bypass password confirmation when needs_password_validation is false', function () { PasswordValidatedForm.showPasswordModal.calls.reset(); const nonPasswordView = createViewFn({ needs_password_confirmation: false }); nonPasswordView._onClickSave(); expect(PasswordValidatedForm.showPasswordModal).not.toHaveBeenCalled(); }); it('should save user', function () { const destName = 'Carlos'; const event = $.Event('click'); spyOn(view, 'killEvent'); spyOn(view, '_getUserFields').and.returnValue({ name: NAME }); spyOn(view, '_getDestinationValues').and.returnValue({ name: destName }); spyOn(view._userModel, 'set'); spyOn(view._userModel, 'save'); view._onClickSave(event); expect(view._userModel.set).toHaveBeenCalledWith({ user: { name: destName } }); expect(view.killEvent).toHaveBeenCalledWith(event); expect(view._userModel.save).toHaveBeenCalledWith( { name: destName }, { wait: true, url: '/api/v3/me', success: showSuccessSpy, error: showErrorsSpy, attrs: { user: { password_confirmation: PASSWORD, name: destName } } }); }); }); it('should not have leaks', function () { view.render(); expect(view).toHaveNoLeaks(); }); afterEach(function () { view.clean(); }); });