app-test.js revision f92e7fd6077d15d365b69901e9fa81bc9e5b495a
YUI.add('app-test', function (Y) {
var ArrayAssert = Y.ArrayAssert,
Assert = Y.Assert,
ObjectAssert = Y.ObjectAssert,
suite,
modelSuite,
modelListSuite,
viewSuite;
// -- Global Suite -------------------------------------------------------------
suite = new Y.Test.Suite('App Framework');
// -- Model Suite --------------------------------------------------------------
modelSuite = new Y.Test.Suite('Model');
// -- Model: Lifecycle ---------------------------------------------------------
modelSuite.add(new Y.Test.Case({
name: 'Lifecycle',
'Models should have `changed` and `lastChange` properties': function () {
var model = new Y.Model();
ObjectAssert.ownsKeys(['changed', 'lastChange'], model);
Assert.isObject(model.changed);
Assert.isObject(model.lastChange);
ObjectAssert.ownsNoKeys(model.changed);
ObjectAssert.ownsNoKeys(model.lastChange);
},
'destroy() should destroy the model instance': function () {
var model = new Y.Model();
model.sync = function () {
Assert.fail('sync should not be called unless the model is being deleted');
};
Assert.isFalse(model.get('destroyed'));
Assert.areSame(model, model.destroy(), 'destroy() should be chainable');
Assert.isTrue(model.get('destroyed'));
},
'destroy() should call a callback if provided as the only arg': function () {
var mock = Y.Mock(),
model = new Y.Model();
Y.Mock.expect(mock, {
method: 'callback',
args : []
});
model.destroy(mock.callback);
Y.Mock.verify(mock);
},
'destroy() should call a callback if provided as the second arg': function () {
var mock = Y.Mock(),
model = new Y.Model();
Y.Mock.expect(mock, {
method: 'callback',
args : []
});
model.destroy({}, mock.callback);
Y.Mock.verify(mock);
},
'destroy() should delete the model if the `delete` option is truthy': function () {
var calls = 0,
mock = Y.Mock(),
model = new Y.Model();
Y.Mock.expect(mock, {
method: 'callback',
args : []
});
model.sync = function (action, options, callback) {
calls += 1;
Assert.areSame('delete', action, 'sync action should be "delete"');
Assert.isObject(options, 'options should be an object');
Assert.isTrue(options['delete'], 'options.delete should be true');
Assert.isFunction(callback, 'callback should be a function');
callback();
};
model.destroy({'delete': true}, mock.callback);
Y.Mock.verify(mock);
}
}));
// -- Model: Attributes --------------------------------------------------------
modelSuite.add(new Y.Test.Case({
name: 'Attributes',
setUp: function () {
this.TestModel = Y.Base.create('testModel', Y.Model, [], {
idAttribute: 'customId'
}, {
ATTRS: {
customId: {value: ''},
foo: {value: ''}
}
});
},
tearDown: function () {
delete this.TestModel;
},
'Attributes should be settable at instantiation time': function () {
var model = new this.TestModel({foo: 'foo'});
Assert.areSame('foo', model.get('foo'));
},
'Custom id attribute should be settable at instantiation time': function () {
var model;
// We need to set and get the id and customId attributes in various
// orders to ensure there are no issues due to the attributes being
// lazily added.
model = new this.TestModel({customId: 'foo'});
Assert.areSame('foo', model.get('customId'));
Assert.areSame('foo', model.get('id'));
model = new this.TestModel({customId: 'foo'});
Assert.areSame('foo', model.get('id'));
Assert.areSame('foo', model.get('customId'));
model = new this.TestModel({id: 'foo'});
Assert.areSame('foo', model.get('customId'));
Assert.areSame('foo', model.get('id'));
model = new this.TestModel({id: 'foo'});
Assert.areSame('foo', model.get('id'));
Assert.areSame('foo', model.get('customId'));
},
'id attribute should be an alias for the custom id attribute': function () {
var calls = 0,
model = new this.TestModel();
// FIXME: Currently there's a bug where getting the 'id' attribute for
// the first time sets the 'customId' attribute to the 'id' attribute's
// default value and fires a change event. This shouldn't happen.
model.get('id');
model.on('change', function (e) {
calls += 1;
Assert.areSame('foo', e.changed.customId.newVal);
Assert.areSame('foo', e.changed.id.newVal);
});
model.set('id', 'foo');
Assert.areSame(1, calls);
},
'clientId attribute should be automatically generated': function () {
var model = new Y.Model();
Assert.isString(model.get('clientId'));
Assert.isTrue(!!model.get('clientId'));
}
}));
// -- Model: Events ------------------------------------------------------------
modelSuite.add(new Y.Test.Case({
name: 'Events',
setUp: function () {
this.TestModel = Y.Base.create('testModel', Y.Model, [], {}, {
ATTRS: {
foo: {value: ''},
bar: {value: ''},
baz: {value: ''}
}
});
},
tearDown: function () {
delete this.TestModel;
},
'`change` event should contain coalesced attribute changes': function () {
var calls = 0,
model = new this.TestModel();
model.on('change', function (e) {
calls += 1;
ObjectAssert.ownsKeys(['foo', 'bar'], e.changed);
Assert.areSame(2, Y.Object.size(e.changed));
ObjectAssert.ownsKeys(['newVal', 'prevVal', 'src'], e.changed.foo);
ObjectAssert.ownsKeys(['newVal', 'prevVal', 'src'], e.changed.bar);
Assert.areSame('foo', e.changed.foo.newVal);
Assert.areSame('', e.changed.foo.prevVal);
Assert.areSame('bar', e.changed.bar.newVal);
Assert.areSame('', e.changed.bar.prevVal);
Assert.areSame('test', e.changed.foo.src);
Assert.areSame('test', e.changed.bar.src);
});
model.setAttrs({
foo: 'foo',
bar: 'bar'
}, {src: 'test'});
Assert.areSame(1, calls);
},
'`change` event should not fire when the _silent_ option is truthy': function () {
var model = new this.TestModel();
model.on('change', function (e) {
Assert.fail('`change` should not fire');
});
model.set('foo', 'bar', {silent: true});
model.setAttrs({bar: 'baz'}, {silent: true});
},
'`error` event should fire when validation fails': function () {
var calls = 0,
model = new this.TestModel();
model.validate = function (hash) {
return 'ERROR. ERROR. DOES NOT COMPUTE.';
};
model.on('error', function (e) {
calls += 1;
Assert.areSame('validate', e.type);
ObjectAssert.ownsKey('foo', e.attributes);
Assert.areSame('bar', e.attributes.foo);
Assert.areSame('ERROR. ERROR. DOES NOT COMPUTE.', e.error);
});
model.set('foo', 'bar');
Assert.areSame(1, calls);
},
'`error` event should fire when parsing fails': function () {
var calls = 0,
model = new this.TestModel();
model.on('error', function (e) {
calls += 1;
Assert.areSame('parse', e.type);
Y.assert(e.error instanceof Error);
Assert.areSame('moo', e.response);
});
model.parse('moo');
Assert.areSame(1, calls);
}
}));
// -- Model: Methods -----------------------------------------------------------
modelSuite.add(new Y.Test.Case({
name: 'Methods'
}));
suite.add(modelSuite);
Y.Test.Runner.add(suite);
}, '@VERSION@', {
requires: ['controller', 'model', 'model-list', 'view', 'test']
});