diff --git a/apps/systemtags/appinfo/app.php b/apps/systemtags/appinfo/app.php index d07902f777..d3886993f8 100644 --- a/apps/systemtags/appinfo/app.php +++ b/apps/systemtags/appinfo/app.php @@ -28,6 +28,7 @@ $eventDispatcher->addListener( \OC_Util::addVendorStyle('select2/select2'); \OCP\Util::addScript('select2-toggleselect'); \OCP\Util::addScript('oc-backbone-webdav'); + \OCP\Util::addScript('systemtags/systemtags'); \OCP\Util::addScript('systemtags/systemtagmodel'); \OCP\Util::addScript('systemtags/systemtagsmappingcollection'); \OCP\Util::addScript('systemtags/systemtagscollection'); diff --git a/apps/systemtags/js/systemtagsinfoview.js b/apps/systemtags/js/systemtagsinfoview.js index b1820bfcd9..2e808f9a84 100644 --- a/apps/systemtags/js/systemtagsinfoview.js +++ b/apps/systemtags/js/systemtagsinfoview.js @@ -9,6 +9,15 @@ */ (function(OCA) { + + function modelToSelection(model) { + var data = model.toJSON(); + if (!OC.isUserAdmin() && !data.userAssignable) { + data.locked = true; + } + return data; + } + /** * @class OCA.SystemTags.SystemTagsInfoView * @classdesc @@ -36,8 +45,9 @@ multiple: true, allowActions: true, allowCreate: true, + isAdmin: OC.isUserAdmin(), initSelection: function(element, callback) { - callback(self.selectedTagsCollection.toJSON()); + callback(self.selectedTagsCollection.map(modelToSelection)); } }); @@ -108,7 +118,7 @@ this.selectedTagsCollection.fetch({ success: function(collection) { collection.fetched = true; - self._inputView.setData(collection.toJSON()); + self._inputView.setData(collection.map(modelToSelection)); self.$el.removeClass('hidden'); } }); diff --git a/apps/systemtags/tests/js/systemtagsinfoviewSpec.js b/apps/systemtags/tests/js/systemtagsinfoviewSpec.js index 971ad8fc17..0fb4e7b22c 100644 --- a/apps/systemtags/tests/js/systemtagsinfoviewSpec.js +++ b/apps/systemtags/tests/js/systemtagsinfoviewSpec.js @@ -20,13 +20,16 @@ */ describe('OCA.SystemTags.SystemTagsInfoView tests', function() { + var isAdminStub; var view; beforeEach(function() { view = new OCA.SystemTags.SystemTagsInfoView(); $('#testArea').append(view.$el); + isAdminStub = sinon.stub(OC, 'isUserAdmin').returns(true); }); afterEach(function() { + isAdminStub.restore(); view.remove(); view = undefined; }); @@ -73,7 +76,7 @@ describe('OCA.SystemTags.SystemTagsInfoView tests', function() { view = new OCA.SystemTags.SystemTagsInfoView(); view.selectedTagsCollection.add([ {id: '1', name: 'test1'}, - {id: '3', name: 'test3'} + {id: '3', name: 'test3', userVisible: false, userAssignable: false} ]); var callback = sinon.stub(); @@ -83,7 +86,31 @@ describe('OCA.SystemTags.SystemTagsInfoView tests', function() { expect(callback.getCall(0).args[0]).toEqual([{ id: '1', name: 'test1', userVisible: true, userAssignable: true }, { - id: '3', name: 'test3', userVisible: true, userAssignable: true + id: '3', name: 'test3', userVisible: false, userAssignable: false + }]); + + inputViewSpy.restore(); + }); + it('sets locked flag on non-assignable tags when user is not an admin', function() { + isAdminStub.returns(false); + + var inputViewSpy = sinon.spy(OC.SystemTags, 'SystemTagsInputField'); + var element = $(''); + view.remove(); + view = new OCA.SystemTags.SystemTagsInfoView(); + view.selectedTagsCollection.add([ + {id: '1', name: 'test1'}, + {id: '3', name: 'test3', userAssignable: false} + ]); + + var callback = sinon.stub(); + inputViewSpy.getCall(0).args[0].initSelection(element, callback); + + expect(callback.calledOnce).toEqual(true); + expect(callback.getCall(0).args[0]).toEqual([{ + id: '1', name: 'test1', userVisible: true, userAssignable: true + }, { + id: '3', name: 'test3', userVisible: true, userAssignable: false, locked: true }]); inputViewSpy.restore(); diff --git a/core/css/systemtags.css b/core/css/systemtags.css index 5c667e5454..d847baa680 100644 --- a/core/css/systemtags.css +++ b/core/css/systemtags.css @@ -69,6 +69,11 @@ margin: 0; line-height: 20px; } + +.systemtags-select2-container .select2-choices .select2-search-choice.select2-locked .label { + font-style: italic; +} + .systemtags-select2-container .select2-choices .select2-search-choice-close { display: none; } diff --git a/core/js/systemtags/systemtagmodel.js b/core/js/systemtags/systemtagmodel.js index e6014977d2..62bf3a7008 100644 --- a/core/js/systemtags/systemtagmodel.js +++ b/core/js/systemtags/systemtagmodel.js @@ -37,8 +37,8 @@ return { id: data.id, name: data.name, - userVisible: data.userVisible === '1', - userAssignable: data.userAssignable === '1' + userVisible: data.userVisible === true || data.userVisible === '1', + userAssignable: data.userAssignable === true || data.userAssignable === '1' }; } }); diff --git a/core/js/systemtags/systemtagsinputfield.js b/core/js/systemtags/systemtagsinputfield.js index facacc50e2..b90ecbe426 100644 --- a/core/js/systemtags/systemtagsinputfield.js +++ b/core/js/systemtags/systemtagsinputfield.js @@ -17,7 +17,11 @@ var RESULT_TEMPLATE = '' + ' ' + + '{{#if isAdmin}}' + + ' {{{tagMarkup}}}' + + '{{else}}' + ' {{name}}' + + '{{/if}}' + '{{#allowActions}}' + ' ' + ' ' + @@ -25,6 +29,14 @@ '{{/allowActions}}' + ''; + var SELECTION_TEMPLATE = + '{{#if isAdmin}}' + + ' {{{tagMarkup}}}' + + '{{else}}' + + ' {{name}}' + + '{{/if}}' + + ''; + var RENAME_FORM_TEMPLATE = '
' + ' ' + @@ -63,6 +75,7 @@ * @param {bool} [options.multiple=false] whether to allow selecting multiple tags * @param {bool} [options.allowActions=true] whether tags can be renamed/delete within the dropdown * @param {bool} [options.allowCreate=true] whether new tags can be created + * @param {bool} [options.isAdmin=true] whether the user is an administrator * @param {Function} options.initSelection function to convert selection to data */ initialize: function(options) { @@ -71,6 +84,7 @@ this._multiple = !!options.multiple; this._allowActions = _.isUndefined(options.allowActions) || !!options.allowActions; this._allowCreate = _.isUndefined(options.allowCreate) || !!options.allowCreate; + this._isAdmin = !!options.isAdmin; if (_.isFunction(options.initSelection)) { this._initSelection = options.initSelection; @@ -223,9 +237,15 @@ _queryTagsAutocomplete: function(query) { var self = this; this.collection.fetch({ - success: function() { + success: function(collection) { + var tagModels = collection.filterByName(query.term); + if (!self._isAdmin) { + tagModels = _.filter(tagModels, function(tagModel) { + return tagModel.get('userAssignable'); + }); + } query.callback({ - results: _.invoke(self.collection.filterByName(query.term), 'toJSON') + results: _.invoke(tagModels, 'toJSON') }); } }); @@ -247,7 +267,25 @@ } return this._resultTemplate(_.extend({ renameTooltip: t('core', 'Rename'), - allowActions: this._allowActions + allowActions: this._allowActions, + tagMarkup: this._isAdmin ? OC.SystemTags.getDescriptiveTag(data)[0].innerHTML : null, + isAdmin: this._isAdmin + }, data)); + }, + + /** + * Formats a single selection item + * + * @param {Object} data data to format + * @return {string} HTML markup + */ + _formatSelection: function(data) { + if (!this._selectionTemplate) { + this._selectionTemplate = Handlebars.compile(SELECTION_TEMPLATE); + } + return this._selectionTemplate(_.extend({ + tagMarkup: this._isAdmin ? OC.SystemTags.getDescriptiveTag(data)[0].innerHTML : null, + isAdmin: this._isAdmin }, data)); }, @@ -266,6 +304,8 @@ this._newTag = { id: -1, name: term, + userAssignable: true, + userVisible: true, isNew: true }; } else { @@ -279,11 +319,20 @@ var self = this; var ids = $(element).val().split(','); + function modelToSelection(model) { + var data = model.toJSON(); + if (!self._isAdmin && !data.userAssignable) { + // lock static tags for non-admins + data.locked = true; + } + return data; + } + function findSelectedObjects(ids) { var selectedModels = self.collection.filter(function(model) { - return ids.indexOf(model.id) >= 0; + return ids.indexOf(model.id) >= 0 && (self._isAdmin || model.get('userVisible')); }); - return _.invoke(selectedModels, 'toJSON'); + return _.map(selectedModels, modelToSelection); } this.collection.fetch({ @@ -316,10 +365,7 @@ }, initSelection: _.bind(this._initSelection, this), formatResult: _.bind(this._formatDropDownResult, this), - formatSelection: function(tag) { - return '' + escapeHTML(tag.name) + '' + - ''; - }, + formatSelection: _.bind(this._formatSelection, this), createSearchChoice: this._allowCreate ? _.bind(this._createSearchChoice, this) : undefined, sortResults: function(results) { var selectedItems = _.pluck(self.$tagsField.select2('data'), 'id'); diff --git a/core/js/tests/specHelper.js b/core/js/tests/specHelper.js index d1c7873f0e..d13691845a 100644 --- a/core/js/tests/specHelper.js +++ b/core/js/tests/specHelper.js @@ -86,6 +86,7 @@ window.firstDay = 0; // setup dummy webroots /* jshint camelcase: false */ window.oc_debug = true; +window.oc_isadmin = false; // FIXME: oc_webroot is supposed to be only the path!!! window.oc_webroot = location.href + '/'; window.oc_appswebroots = { diff --git a/core/js/tests/specs/systemtags/systemtagsinputfieldSpec.js b/core/js/tests/specs/systemtags/systemtagsinputfieldSpec.js index dc8d2ec82f..07e926cd2a 100644 --- a/core/js/tests/specs/systemtags/systemtagsinputfieldSpec.js +++ b/core/js/tests/specs/systemtags/systemtagsinputfieldSpec.js @@ -27,8 +27,6 @@ describe('OC.SystemTags.SystemTagsInputField tests', function() { select2Stub = sinon.stub($.fn, 'select2'); select2Stub.returnsThis(); $('#testArea').append($container); - view = new OC.SystemTags.SystemTagsInputField(); - $container.append(view.$el); }); afterEach(function() { select2Stub.restore(); @@ -36,273 +34,384 @@ describe('OC.SystemTags.SystemTagsInputField tests', function() { view.remove(); view = undefined; }); - describe('rendering', function() { - beforeEach(function() { - view.render(); - }); - it('calls select2 on rendering', function() { - expect(view.$el.find('input[name=tags]').length).toEqual(1); - expect(select2Stub.called).toEqual(true); - }); - it('formatResult renders rename button', function() { - var opts = select2Stub.getCall(0).args[0]; - var $el = $(opts.formatResult({id: '1', name: 'test'})); - expect($el.find('.label').text()).toEqual('test'); - expect($el.find('.rename').length).toEqual(1); - }); - }); - describe('initSelection', function() { - var fetchStub; - var testTags; - - beforeEach(function() { - fetchStub = sinon.stub(OC.SystemTags.SystemTagsCollection.prototype, 'fetch'); - testTags = [ - new OC.SystemTags.SystemTagModel({id: '1', name: 'test1'}), - new OC.SystemTags.SystemTagModel({id: '2', name: 'test2'}), - new OC.SystemTags.SystemTagModel({id: '3', name: 'test3'}), - ]; - view.render(); - }); - afterEach(function() { - fetchStub.restore(); - }); - it('grabs values from the full collection', function() { - var $el = view.$el.find('input'); - $el.val('1,3'); - var opts = select2Stub.getCall(0).args[0]; - var callback = sinon.stub(); - opts.initSelection($el, callback); - - expect(fetchStub.calledOnce).toEqual(true); - view.collection.add(testTags); - fetchStub.yieldTo('success', view.collection); - - expect(callback.calledOnce).toEqual(true); - var models = callback.getCall(0).args[0]; - expect(models.length).toEqual(2); - expect(models[0].id).toEqual('1'); - expect(models[0].name).toEqual('test1'); - expect(models[1].id).toEqual('3'); - expect(models[1].name).toEqual('test3'); - }); - }); - describe('tag selection', function() { - beforeEach(function() { - view.render(); - var $el = view.$el.find('input'); - $el.val('1'); - - view.collection.add([ - new OC.SystemTags.SystemTagModel({id: '1', name: 'abc'}), - new OC.SystemTags.SystemTagModel({id: '2', name: 'def'}), - new OC.SystemTags.SystemTagModel({id: '3', name: 'abd'}), - ]); - }); - afterEach(function() { - }); - it('does not create dummy tag when user types non-matching name', function() { - var opts = select2Stub.getCall(0).args[0]; - var result = opts.createSearchChoice('abc'); - expect(result).not.toBeDefined(); - }); - it('creates dummy tag when user types non-matching name', function() { - var opts = select2Stub.getCall(0).args[0]; - var result = opts.createSearchChoice('abnew'); - expect(result.id).toEqual(-1); - expect(result.name).toEqual('abnew'); - expect(result.isNew).toEqual(true); - }); - it('creates the real tag and fires select event after user selects the dummy tag', function() { - var selectHandler = sinon.stub(); - view.on('select', selectHandler); - var createStub = sinon.stub(OC.SystemTags.SystemTagsCollection.prototype, 'create'); - view.$el.find('input').trigger(new $.Event('select2-selecting', { - object: { - id: -1, - name: 'newname', - isNew: true - } - })); - - expect(createStub.calledOnce).toEqual(true); - expect(createStub.getCall(0).args[0]).toEqual({ - name: 'newname', - userVisible: true, - userAssignable: true - }); - - var newModel = new OC.SystemTags.SystemTagModel({ - id: '123', - name: 'newname', - userVisible: true, - userAssignable: true - }); - - // not called yet - expect(selectHandler.notCalled).toEqual(true); - - select2Stub.withArgs('data').returns([{ - id: '1', - name: 'abc' - }]); - - createStub.yieldTo('success', newModel); - - expect(select2Stub.lastCall.args[0]).toEqual('data'); - expect(select2Stub.lastCall.args[1]).toEqual([{ - id: '1', - name: 'abc' - }, - newModel.toJSON() - ]); - - expect(selectHandler.calledOnce).toEqual(true); - expect(selectHandler.getCall(0).args[0]).toEqual(newModel); - - createStub.restore(); - }); - it('triggers select event after selecting an existing tag', function() { - var selectHandler = sinon.stub(); - view.on('select', selectHandler); - view.$el.find('input').trigger(new $.Event('select2-selecting', { - object: { - id: '2', - name: 'def' - } - })); - - expect(selectHandler.calledOnce).toEqual(true); - expect(selectHandler.getCall(0).args[0]).toEqual(view.collection.get('2')); - }); - it('triggers deselect event after deselecting an existing tag', function() { - var selectHandler = sinon.stub(); - view.on('deselect', selectHandler); - view.$el.find('input').trigger(new $.Event('select2-removing', { - choice: { - id: '2', - name: 'def' - } - })); - - expect(selectHandler.calledOnce).toEqual(true); - expect(selectHandler.getCall(0).args[0]).toEqual('2'); - }); - }); - describe('autocomplete', function() { - var fetchStub, opts; - - beforeEach(function() { - fetchStub = sinon.stub(OC.SystemTags.SystemTagsCollection.prototype, 'fetch'); - view.render(); - opts = select2Stub.getCall(0).args[0]; - - view.collection.add([ - new OC.SystemTags.SystemTagModel({id: '1', name: 'abc'}), - new OC.SystemTags.SystemTagModel({id: '2', name: 'def'}), - new OC.SystemTags.SystemTagModel({id: '3', name: 'abd'}), - ]); - }); - afterEach(function() { - fetchStub.restore(); - }); - it('completes results', function() { - var callback = sinon.stub(); - opts.query({ - term: 'ab', - callback: callback - }); - expect(fetchStub.calledOnce).toEqual(true); - - fetchStub.yieldTo('success', view.collection); - - expect(callback.calledOnce).toEqual(true); - expect(callback.getCall(0).args[0].results).toEqual([ - { - id: '1', - name: 'abc', - userVisible: true, - userAssignable: true - }, - { - id: '3', - name: 'abd', - userVisible: true, - userAssignable: true - } - ]); - }); - }); - describe('tag actions', function() { - var $dropdown, opts; + + describe('general behavior', function() { + var $dropdown; beforeEach(function() { + view = new OC.SystemTags.SystemTagsInputField(); + $('.testInputContainer').append(view.$el); $dropdown = $('
'); select2Stub.withArgs('dropdown').returns($dropdown); $('#testArea').append($dropdown); view.render(); - - opts = select2Stub.getCall(0).args[0]; - - view.collection.add([ - new OC.SystemTags.SystemTagModel({id: '1', name: 'abc'}), - ]); - - $dropdown.append(opts.formatResult(view.collection.get('1').toJSON())); - }); - afterEach(function() { + describe('rendering', function() { + it('calls select2 on rendering', function() { + expect(view.$el.find('input[name=tags]').length).toEqual(1); + expect(select2Stub.called).toEqual(true); + }); + it('formatResult renders rename button', function() { + var opts = select2Stub.getCall(0).args[0]; + var $el = $(opts.formatResult({id: '1', name: 'test'})); + expect($el.find('.rename').length).toEqual(1); + }); }); - it('displays rename form when clicking rename', function() { - $dropdown.find('.rename').mouseup(); - expect($dropdown.find('form.systemtags-rename-form').length).toEqual(1); - expect($dropdown.find('form.systemtags-rename-form input').val()).toEqual('abc'); + describe('tag selection', function() { + beforeEach(function() { + var $el = view.$el.find('input'); + $el.val('1'); + + view.collection.add([ + new OC.SystemTags.SystemTagModel({id: '1', name: 'abc'}), + new OC.SystemTags.SystemTagModel({id: '2', name: 'def'}), + new OC.SystemTags.SystemTagModel({id: '3', name: 'abd', userAssignable: false}), + ]); + }); + it('does not create dummy tag when user types non-matching name', function() { + var opts = select2Stub.getCall(0).args[0]; + var result = opts.createSearchChoice('abc'); + expect(result).not.toBeDefined(); + }); + it('creates dummy tag when user types non-matching name', function() { + var opts = select2Stub.getCall(0).args[0]; + var result = opts.createSearchChoice('abnew'); + expect(result.id).toEqual(-1); + expect(result.name).toEqual('abnew'); + expect(result.isNew).toEqual(true); + expect(result.userVisible).toEqual(true); + expect(result.userAssignable).toEqual(true); + }); + it('creates the real tag and fires select event after user selects the dummy tag', function() { + var selectHandler = sinon.stub(); + view.on('select', selectHandler); + var createStub = sinon.stub(OC.SystemTags.SystemTagsCollection.prototype, 'create'); + view.$el.find('input').trigger(new $.Event('select2-selecting', { + object: { + id: -1, + name: 'newname', + isNew: true + } + })); + + expect(createStub.calledOnce).toEqual(true); + expect(createStub.getCall(0).args[0]).toEqual({ + name: 'newname', + userVisible: true, + userAssignable: true + }); + + var newModel = new OC.SystemTags.SystemTagModel({ + id: '123', + name: 'newname', + userVisible: true, + userAssignable: true + }); + + // not called yet + expect(selectHandler.notCalled).toEqual(true); + + select2Stub.withArgs('data').returns([{ + id: '1', + name: 'abc' + }]); + + createStub.yieldTo('success', newModel); + + expect(select2Stub.lastCall.args[0]).toEqual('data'); + expect(select2Stub.lastCall.args[1]).toEqual([{ + id: '1', + name: 'abc' + }, + newModel.toJSON() + ]); + + expect(selectHandler.calledOnce).toEqual(true); + expect(selectHandler.getCall(0).args[0]).toEqual(newModel); + + createStub.restore(); + }); + it('triggers select event after selecting an existing tag', function() { + var selectHandler = sinon.stub(); + view.on('select', selectHandler); + view.$el.find('input').trigger(new $.Event('select2-selecting', { + object: { + id: '2', + name: 'def' + } + })); + + expect(selectHandler.calledOnce).toEqual(true); + expect(selectHandler.getCall(0).args[0]).toEqual(view.collection.get('2')); + }); + it('triggers deselect event after deselecting an existing tag', function() { + var selectHandler = sinon.stub(); + view.on('deselect', selectHandler); + view.$el.find('input').trigger(new $.Event('select2-removing', { + choice: { + id: '2', + name: 'def' + } + })); + + expect(selectHandler.calledOnce).toEqual(true); + expect(selectHandler.getCall(0).args[0]).toEqual('2'); + }); }); - it('renames model and submits change when submitting form', function() { - var saveStub = sinon.stub(OC.SystemTags.SystemTagModel.prototype, 'save'); - $dropdown.find('.rename').mouseup(); - $dropdown.find('form input').val('abc_renamed'); - $dropdown.find('form').trigger(new $.Event('submit')); + describe('tag actions', function() { + var opts; - expect(saveStub.calledOnce).toEqual(true); - expect(saveStub.getCall(0).args[0]).toEqual({'name': 'abc_renamed'}); + beforeEach(function() { - expect($dropdown.find('.label').text()).toEqual('abc_renamed'); - expect($dropdown.find('form').length).toEqual(0); + opts = select2Stub.getCall(0).args[0]; - saveStub.restore(); + view.collection.add([ + new OC.SystemTags.SystemTagModel({id: '1', name: 'abc'}), + ]); + + $dropdown.append(opts.formatResult(view.collection.get('1').toJSON())); + + }); + it('displays rename form when clicking rename', function() { + $dropdown.find('.rename').mouseup(); + expect($dropdown.find('form.systemtags-rename-form').length).toEqual(1); + expect($dropdown.find('form.systemtags-rename-form input').val()).toEqual('abc'); + }); + it('renames model and submits change when submitting form', function() { + var saveStub = sinon.stub(OC.SystemTags.SystemTagModel.prototype, 'save'); + $dropdown.find('.rename').mouseup(); + $dropdown.find('form input').val('abc_renamed'); + $dropdown.find('form').trigger(new $.Event('submit')); + + expect(saveStub.calledOnce).toEqual(true); + expect(saveStub.getCall(0).args[0]).toEqual({'name': 'abc_renamed'}); + + expect($dropdown.find('.label').text()).toEqual('abc_renamed'); + expect($dropdown.find('form').length).toEqual(0); + + saveStub.restore(); + }); + it('deletes model and submits change when clicking delete', function() { + var destroyStub = sinon.stub(OC.SystemTags.SystemTagModel.prototype, 'destroy'); + + expect($dropdown.find('.delete').length).toEqual(0); + $dropdown.find('.rename').mouseup(); + // delete button appears + expect($dropdown.find('.delete').length).toEqual(1); + $dropdown.find('.delete').mouseup(); + + expect(destroyStub.calledOnce).toEqual(true); + expect(destroyStub.calledOn(view.collection.get('1'))); + + destroyStub.restore(); + }); }); - it('deletes model and submits change when clicking delete', function() { - var destroyStub = sinon.stub(OC.SystemTags.SystemTagModel.prototype, 'destroy'); - - expect($dropdown.find('.delete').length).toEqual(0); - $dropdown.find('.rename').mouseup(); - // delete button appears - expect($dropdown.find('.delete').length).toEqual(1); - $dropdown.find('.delete').mouseup(); - - expect(destroyStub.calledOnce).toEqual(true); - expect(destroyStub.calledOn(view.collection.get('1'))); - - destroyStub.restore(); + describe('setting data', function() { + it('sets value when calling setValues', function() { + var vals = ['1', '2']; + view.setValues(vals); + expect(select2Stub.lastCall.args[0]).toEqual('val'); + expect(select2Stub.lastCall.args[1]).toEqual(vals); + }); + it('sets data when calling setData', function() { + var vals = [{id: '1', name: 'test1'}, {id: '2', name: 'test2'}]; + view.setData(vals); + expect(select2Stub.lastCall.args[0]).toEqual('data'); + expect(select2Stub.lastCall.args[1]).toEqual(vals); + }); }); }); - describe('setting data', function() { + + describe('as admin', function() { beforeEach(function() { + view = new OC.SystemTags.SystemTagsInputField({ + isAdmin: true + }); view.render(); + $('.testInputContainer').append(view.$el); }); - it('sets value when calling setValues', function() { - var vals = ['1', '2']; - view.setValues(vals); - expect(select2Stub.lastCall.args[0]).toEqual('val'); - expect(select2Stub.lastCall.args[1]).toEqual(vals); + it('formatResult renders tag name with visibility', function() { + var opts = select2Stub.getCall(0).args[0]; + var $el = $(opts.formatResult({id: '1', name: 'test', userVisible: false, userAssignable: false})); + expect($el.find('.label').text()).toEqual('test (invisible, not assignable)'); }); - it('sets data when calling setData', function() { - var vals = [{id: '1', name: 'test1'}, {id: '2', name: 'test2'}]; - view.setData(vals); - expect(select2Stub.lastCall.args[0]).toEqual('data'); - expect(select2Stub.lastCall.args[1]).toEqual(vals); + it('formatSelection renders tag name with visibility', function() { + var opts = select2Stub.getCall(0).args[0]; + var $el = $(opts.formatSelection({id: '1', name: 'test', userVisible: false, userAssignable: false})); + expect($el.text().trim()).toEqual('test (invisible, not assignable),'); + }); + describe('initSelection', function() { + var fetchStub; + var testTags; + + beforeEach(function() { + fetchStub = sinon.stub(OC.SystemTags.SystemTagsCollection.prototype, 'fetch'); + testTags = [ + new OC.SystemTags.SystemTagModel({id: '1', name: 'test1'}), + new OC.SystemTags.SystemTagModel({id: '2', name: 'test2'}), + new OC.SystemTags.SystemTagModel({id: '3', name: 'test3', userAssignable: false}), + ]; + }); + afterEach(function() { + fetchStub.restore(); + }); + it('grabs values from the full collection', function() { + var $el = view.$el.find('input'); + $el.val('1,3'); + var opts = select2Stub.getCall(0).args[0]; + var callback = sinon.stub(); + opts.initSelection($el, callback); + + expect(fetchStub.calledOnce).toEqual(true); + view.collection.add(testTags); + fetchStub.yieldTo('success', view.collection); + + expect(callback.calledOnce).toEqual(true); + var models = callback.getCall(0).args[0]; + expect(models.length).toEqual(2); + expect(models[0].id).toEqual('1'); + expect(models[0].name).toEqual('test1'); + expect(models[1].id).toEqual('3'); + expect(models[1].name).toEqual('test3'); + }); + }); + describe('autocomplete', function() { + var fetchStub, opts; + + beforeEach(function() { + fetchStub = sinon.stub(OC.SystemTags.SystemTagsCollection.prototype, 'fetch'); + opts = select2Stub.getCall(0).args[0]; + + view.collection.add([ + new OC.SystemTags.SystemTagModel({id: '1', name: 'abc'}), + new OC.SystemTags.SystemTagModel({id: '2', name: 'def'}), + new OC.SystemTags.SystemTagModel({id: '3', name: 'abd', userAssignable: false}), + ]); + }); + afterEach(function() { + fetchStub.restore(); + }); + it('completes results', function() { + var callback = sinon.stub(); + opts.query({ + term: 'ab', + callback: callback + }); + expect(fetchStub.calledOnce).toEqual(true); + + fetchStub.yieldTo('success', view.collection); + + expect(callback.calledOnce).toEqual(true); + expect(callback.getCall(0).args[0].results).toEqual([ + { + id: '1', + name: 'abc', + userVisible: true, + userAssignable: true + }, + { + id: '3', + name: 'abd', + userVisible: true, + userAssignable: false + } + ]); + }); + }); + }); + + describe('as user', function() { + beforeEach(function() { + view = new OC.SystemTags.SystemTagsInputField({ + isAdmin: false + }); + view.render(); + $('.testInputContainer').append(view.$el); + }); + it('formatResult renders tag name only', function() { + var opts = select2Stub.getCall(0).args[0]; + var $el = $(opts.formatResult({id: '1', name: 'test'})); + expect($el.find('.label').text()).toEqual('test'); + }); + it('formatSelection renders tag name only', function() { + var opts = select2Stub.getCall(0).args[0]; + var $el = $(opts.formatSelection({id: '1', name: 'test'})); + expect($el.text().trim()).toEqual('test,'); + }); + describe('initSelection', function() { + var fetchStub; + var testTags; + + beforeEach(function() { + fetchStub = sinon.stub(OC.SystemTags.SystemTagsCollection.prototype, 'fetch'); + testTags = [ + new OC.SystemTags.SystemTagModel({id: '1', name: 'test1'}), + new OC.SystemTags.SystemTagModel({id: '2', name: 'test2'}), + new OC.SystemTags.SystemTagModel({id: '3', name: 'test3', userAssignable: false}), + ]; + view.render(); + }); + afterEach(function() { + fetchStub.restore(); + }); + it('grabs values from the full collection', function() { + var $el = view.$el.find('input'); + $el.val('1,3'); + var opts = select2Stub.getCall(0).args[0]; + var callback = sinon.stub(); + opts.initSelection($el, callback); + + expect(fetchStub.calledOnce).toEqual(true); + view.collection.add(testTags); + fetchStub.yieldTo('success', view.collection); + + expect(callback.calledOnce).toEqual(true); + var models = callback.getCall(0).args[0]; + expect(models.length).toEqual(2); + expect(models[0].id).toEqual('1'); + expect(models[0].name).toEqual('test1'); + expect(models[1].id).toEqual('3'); + expect(models[1].name).toEqual('test3'); + }); + }); + describe('autocomplete', function() { + var fetchStub, opts; + + beforeEach(function() { + fetchStub = sinon.stub(OC.SystemTags.SystemTagsCollection.prototype, 'fetch'); + view.render(); + opts = select2Stub.getCall(0).args[0]; + + view.collection.add([ + new OC.SystemTags.SystemTagModel({id: '1', name: 'abc'}), + new OC.SystemTags.SystemTagModel({id: '2', name: 'def'}), + new OC.SystemTags.SystemTagModel({id: '3', name: 'abd', userAssignable: false}), + ]); + }); + afterEach(function() { + fetchStub.restore(); + }); + it('completes results excluding non-assignable tags', function() { + var callback = sinon.stub(); + opts.query({ + term: 'ab', + callback: callback + }); + expect(fetchStub.calledOnce).toEqual(true); + + fetchStub.yieldTo('success', view.collection); + + expect(callback.calledOnce).toEqual(true); + expect(callback.getCall(0).args[0].results).toEqual([ + { + id: '1', + name: 'abc', + userVisible: true, + userAssignable: true + } + ]); + }); }); }); });