From 4facd262bd53a125cd2297ba3ddfe76c51afc818 Mon Sep 17 00:00:00 2001 From: cahrens Date: Mon, 20 May 2013 16:26:48 -0400 Subject: [PATCH] Jasmine test for metadata model. --- .../coffee/spec/models/metadata_spec.coffee | 59 ++++++++++++++++++- .../coffee/spec/views/module_edit_spec.coffee | 10 ---- cms/static/js/models/metadata_model.js | 43 ++++++++++++-- cms/static/js/views/metadata_editor_view.js | 12 ++-- 4 files changed, 103 insertions(+), 21 deletions(-) diff --git a/cms/static/coffee/spec/models/metadata_spec.coffee b/cms/static/coffee/spec/models/metadata_spec.coffee index 8dc771b339..5ff65e1bfa 100644 --- a/cms/static/coffee/spec/models/metadata_spec.coffee +++ b/cms/static/coffee/spec/models/metadata_spec.coffee @@ -1,3 +1,58 @@ describe "CMS.Models.Metadata", -> - it "has no url", -> - expect(new CMS.Models.Metadata().url).toEqual("/save_item") \ No newline at end of file + it "knows when the value has not been modified", -> + model = new CMS.Models.Metadata( + {'value': 'original', 'explicitly_set': false}) + expect(model.isModified()).toBeFalsy() + + model = new CMS.Models.Metadata( + {'value': 'original', 'explicitly_set': true}) + model.setValue('original') + expect(model.isModified()).toBeFalsy() + + it "knows when the value has been modified", -> + model = new CMS.Models.Metadata( + {'value': 'original', 'explicitly_set': false}) + model.setValue('original') + expect(model.isModified()).toBeTruthy() + + model = new CMS.Models.Metadata( + {'value': 'original', 'explicitly_set': true}) + model.setValue('modified') + expect(model.isModified()).toBeTruthy() + + it "tracks when values have been explicitly set", -> + model = new CMS.Models.Metadata( + {'value': 'original', 'explicitly_set': false}) + expect(model.isExplicitlySet()).toBeFalsy() + model.setValue('original') + expect(model.isExplicitlySet()).toBeTruthy() + + it "has both 'display value' and a 'value' methods", -> + model = new CMS.Models.Metadata( + {'value': 'default', 'explicitly_set': false}) + expect(model.getValue()).toBeNull + expect(model.getDisplayValue()).toBe('default') + model.setValue('modified') + expect(model.getValue()).toBe('modified') + expect(model.getDisplayValue()).toBe('modified') + + it "has a clear method for reverting to the default", -> + model = new CMS.Models.Metadata( + {'value': 'original', 'default_value' : 'default', 'explicitly_set': true}) + model.clear() + expect(model.getValue()).toBeNull + expect(model.getDisplayValue()).toBe('default') + expect(model.isExplicitlySet()).toBeFalsy() + + it "has a getter for field name", -> + model = new CMS.Models.Metadata({'field_name': 'foo'}) + expect(model.getFieldName()).toBe('foo') + + it "has a getter for options", -> + model = new CMS.Models.Metadata({'options': ['foo', 'bar']}) + expect(model.getOptions()).toEqual(['foo', 'bar']) + + it "has a getter for type", -> + model = new CMS.Models.Metadata({'type': 'Integer'}) + expect(model.getType()).toBe(CMS.Models.Metadata.INTEGER_TYPE) + diff --git a/cms/static/coffee/spec/views/module_edit_spec.coffee b/cms/static/coffee/spec/views/module_edit_spec.coffee index baf9ee9c20..d2457d175f 100644 --- a/cms/static/coffee/spec/views/module_edit_spec.coffee +++ b/cms/static/coffee/spec/views/module_edit_spec.coffee @@ -73,13 +73,3 @@ describe "CMS.Views.ModuleEdit", -> expect(XModule.loadModule).toHaveBeenCalled() expect(XModule.loadModule.mostRecentCall.args[0]).toBe($('.xmodule_display')) - describe "changedMetadata", -> - it "returns empty if no metadata loaded", -> - expect(@moduleEdit.changedMetadata()).toEqual({}) - - it "returns only changed values", -> - @moduleEdit.originalMetadata = {'foo', 'bar'} - spyOn(@moduleEdit, 'metadata').andReturn({'a': '', 'b': 'before', 'c': ''}) - @moduleEdit.loadEdit() - @moduleEdit.metadata.andReturn({'a': '', 'b': 'after', 'd': 'only_after'}) - expect(@moduleEdit.changedMetadata()).toEqual({'b' : 'after', 'd' : 'only_after'}) diff --git a/cms/static/js/models/metadata_model.js b/cms/static/js/models/metadata_model.js index 2cf15178ca..a3f8136376 100644 --- a/cms/static/js/models/metadata_model.js +++ b/cms/static/js/models/metadata_model.js @@ -19,10 +19,10 @@ CMS.Models.Metadata = Backbone.Model.extend({ this.original_explicitly_set = this.get('explicitly_set'); }, - getOriginalValue: function() { - return this.originalValue; - }, - + /** + * Returns true if the stored value is different, or if the "explicitly_set" + * property has changed. + */ isModified : function() { if (!this.get('explicitly_set') && !this.original_explicitly_set) { return false; @@ -33,37 +33,72 @@ CMS.Models.Metadata = Backbone.Model.extend({ return true; }, + /** + * Returns true if a non-default/non-inherited value has been set. + */ isExplicitlySet: function() { return this.get('explicitly_set'); }, + /** + * The value, as shown in the UI. This may be an inherited or default value. + */ getDisplayValue : function () { return this.get('value'); }, + /** + * The value, as should be returned to the server. if 'isExplicitlySet' + * returns false, this method returns null to indicate that the value + * is not set at this level. + */ getValue: function() { return this.get('explicitly_set') ? this.get('value') : null; }, + /** + * Sets the displayed value. + */ setValue: function (value) { this.set('explicitly_set', true); this.set('value', value); }, + /** + * Returns the field name, which should be used for persisting the metadata + * field to the server. + */ getFieldName: function () { return this.get('field_name'); }, + /** + * Returns the options. This may be a array of possible values, or an object + * with properties like "max", "min" and "step". + */ getOptions: function () { return this.get('options'); }, + /** + * Returns the type of this metadata field. Possible values are SELECT_TYPE, + * INTEGER_TYPE, and FLOAT_TYPE, GENERIC_TYPE. + */ getType: function() { return this.get('type'); }, + /** + * Reverts the value to the default_value specified at construction, and updates the + * explicitly_set property. + */ clear: function() { this.set('explicitly_set', false); this.set('value', this.get('default_value')); } }); + +CMS.Models.Metadata.SELECT_TYPE = "Select"; +CMS.Models.Metadata.INTEGER_TYPE = "Integer"; +CMS.Models.Metadata.FLOAT_TYPE = "Float"; +CMS.Models.Metadata.GENERIC_TYPE = "Generic"; diff --git a/cms/static/js/views/metadata_editor_view.js b/cms/static/js/views/metadata_editor_view.js index 61a2504c56..fa2df079a9 100644 --- a/cms/static/js/views/metadata_editor_view.js +++ b/cms/static/js/views/metadata_editor_view.js @@ -2,9 +2,7 @@ if (!CMS.Views['Metadata']) CMS.Views.Metadata = {}; CMS.Views.Metadata.Editor = Backbone.View.extend({ - // Model class is ... - events : { - }, + // Model is simply a Backbone.Model instance. initialize : function() { var self = this; @@ -32,13 +30,15 @@ CMS.Views.Metadata.Editor = Backbone.View.extend({ el: self.$el.find('.metadata_entry')[counter++], model: model }; - if (item.type === 'Select') { + if (item.type === CMS.Models.Metadata.SELECT_TYPE) { new CMS.Views.Metadata.Option(data); } - else if (item.type === 'Integer' || item.type === 'Float') { + else if (item.type === CMS.Models.Metadata.INTEGER_TYPE || + item.type === CMS.Models.Metadata.FLOAT_TYPE) { new CMS.Views.Metadata.Number(data); } else { + // Everything else is treated as GENERIC_TYPE, which uses String editor. new CMS.Views.Metadata.String(data); } }); @@ -67,6 +67,8 @@ CMS.Views.Metadata.Editor = Backbone.View.extend({ CMS.Views.Metadata.AbstractEditor = Backbone.View.extend({ + // Model is CMS.Models.Metadata. + initialize : function() { var self = this; var templateName = this.getTemplateName();