Commit 5cd58897 by Daniel Friedman

Require unique group names in group configurations

TNL-1142
parent c95d90a3
......@@ -7,7 +7,9 @@ define([
var experimentGroupConfigurations = new GroupConfigurationCollection(
experimentGroupConfigurationsJson, {parse: true}
),
contentGroupConfiguration = new GroupConfigurationModel(contentGroupConfigurationJson, {parse: true});
contentGroupConfiguration = new GroupConfigurationModel(contentGroupConfigurationJson, {
parse: true, canBeEmpty: true
});
experimentGroupConfigurations.url = groupConfigurationUrl;
experimentGroupConfigurations.outlineUrl = courseOutlineUrl;
......
......@@ -35,7 +35,8 @@ function(Backbone, _, str, gettext, GroupModel, GroupCollection) {
collectionType: GroupCollection
}],
initialize: function() {
initialize: function(attributes, options) {
this.canBeEmpty = options && options.canBeEmpty;
this.setOriginalAttributes();
return this;
},
......@@ -45,7 +46,7 @@ function(Backbone, _, str, gettext, GroupModel, GroupCollection) {
},
reset: function() {
this.set(this._originalAttributes, { parse: true });
this.set(this._originalAttributes, { parse: true, validate: true });
},
isDirty: function() {
......@@ -87,23 +88,35 @@ function(Backbone, _, str, gettext, GroupModel, GroupCollection) {
};
}
if (attrs.groups.length < 1) {
if (!this.canBeEmpty && attrs.groups.length < 1) {
return {
message: gettext('There must be at least one group.'),
attributes: { groups: true }
};
} else {
// validate all groups
var invalidGroups = [];
var validGroups = new Backbone.Collection(),
invalidGroups = new Backbone.Collection();
attrs.groups.each(function(group) {
if(!group.isValid()) {
invalidGroups.push(group);
if (!group.isValid()) {
invalidGroups.add(group);
} else {
validGroups.add(group);
}
});
if (!_.isEmpty(invalidGroups)) {
if (!invalidGroups.isEmpty()) {
return {
message: gettext('All groups must have a name.'),
attributes: { groups: invalidGroups }
attributes: { groups: invalidGroups.toJSON() }
};
}
var groupNames = validGroups.map(function(group) { return group.get('name'); });
if (groupNames.length !== _.uniq(groupNames).length) {
return {
message: gettext('All groups must have a unique name.'),
attributes: { groups: validGroups.toJSON() }
};
}
}
......
......@@ -48,10 +48,12 @@ define([
});
it('should be able to reset itself', function() {
this.model.set('name', 'foobar');
this.model.reset();
var originalName = 'Original Name',
model = new GroupConfigurationModel({name: originalName});
model.set({name: 'New Name'});
model.reset();
expect(this.model.get('name')).toEqual('');
expect(model.get('name')).toEqual(originalName);
});
it('should be dirty after it\'s been changed', function() {
......@@ -149,10 +151,42 @@ define([
});
it('can pass validation', function() {
// Note that two groups - Group A and Group B - are
// created by default.
var model = new GroupConfigurationModel({ name: 'foo' });
expect(model.isValid()).toBeTruthy();
});
it('requires at least one group', function() {
var group1 = new GroupModel({ name: 'Group A' }),
model = new GroupConfigurationModel({ name: 'foo', groups: [] });
expect(model.isValid()).toBeFalsy();
model.get('groups').add(group1);
expect(model.isValid()).toBeTruthy();
});
it('requires a valid group', function() {
var model = new GroupConfigurationModel({ name: 'foo', groups: [{ name: '' }] });
expect(model.isValid()).toBeFalsy();
});
it('requires all groups to be valid', function() {
var model = new GroupConfigurationModel({ name: 'foo', groups: [{ name: 'Group A' }, { name: '' }] });
expect(model.isValid()).toBeFalsy();
});
it('requires all groups to have unique names', function() {
var model = new GroupConfigurationModel({
name: 'foo', groups: [{ name: 'Group A' }, { name: 'Group A' }]
});
expect(model.isValid()).toBeFalsy();
});
});
});
......@@ -184,36 +218,6 @@ define([
expect(model.isValid()).toBeTruthy();
});
it('requires at least one group', function() {
var group1 = new GroupModel({ name: 'Group A' }),
model = new GroupConfigurationModel({ name: 'foo' });
model.get('groups').reset([]);
expect(model.isValid()).toBeFalsy();
model.get('groups').add(group1);
expect(model.isValid()).toBeTruthy();
});
it('requires a valid group', function() {
var group = new GroupModel(),
model = new GroupConfigurationModel({ name: 'foo' });
model.get('groups').reset([group]);
expect(model.isValid()).toBeFalsy();
});
it('requires all groups to be valid', function() {
var group1 = new GroupModel({ name: 'Group A' }),
group2 = new GroupModel(),
model = new GroupConfigurationModel({ name: 'foo' });
model.get('groups').reset([group1, group2]);
expect(model.isValid()).toBeFalsy();
});
});
});
......
......@@ -659,7 +659,7 @@ define([
id: 0,
name: 'Content Group Configuration',
groups: groups
});
}, {canBeEmpty: true});
groupConfiguration.urlRoot = '/mock_url';
return groups;
};
......
......@@ -18,7 +18,7 @@ define([
) {
'use strict';
var ListItemView = BaseView.extend({
var ListItemView = BaseView.extend({
canDelete: false,
initialize: function() {
......
......@@ -17,11 +17,12 @@ define([
var ListItemEditorView = BaseView.extend({
initialize: function() {
this.listenTo(this.model, 'invalid', this.render);
this.listenTo(this.getSaveableModel(), 'invalid', this.render);
},
render: function() {
this.$el.html(this.template(_.extend({
error: this.model.validationError
error: this.model.validationError || this.getSaveableModel().validationError
}, this.getTemplateOptions())));
},
......@@ -29,7 +30,7 @@ define([
if (event && event.preventDefault) { event.preventDefault(); }
this.setValues();
if (!this.model.isValid()) {
if (!this.model.isValid() || !this.getSaveableModel().isValid()) {
return false;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment