DIR : /home/kozerus/public_html/pn/uize/site-source/js/Uize/Test/Uize/Data/Diff.js
/home/kozerus/public_html/pn/uize/site-source/js/Uize/Test/Uize/Data
/*______________
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
| / / | ---------------------------------------------------
| / O / | MODULE : Uize.Test.Uize.Data.Diff Class
| / / / |
| / / / /| | ONLINE : http://www.uize.com
| /____/ /__/_| | COPYRIGHT : (c)2014-2016 UIZE
| /___ | LICENSE : Available under MIT License or GNU General Public License
|_______________| http://www.uize.com/license.html
*/
/* Module Meta Data
type: Test
importance: 1
codeCompleteness: 100
docCompleteness: 100
*/
/*?
Introduction
The =Uize.Test.Uize.Data.Diff= module defines a suite of unit tests for the =Uize.Data.Diff= module.
*DEVELOPERS:* `Chris van Rensburg`
*/
Uize.module ({
name:'Uize.Test.Uize.Data.Diff',
required:'Uize.Test',
builder:function () {
'use strict';
function _addedOrModifiedValuesPropertyComparer (_object1Property,_object2Property) {
return (
_object2Property && (!_object1Property || _object2Property.value !== _object1Property.value)
? _object2Property
: undefined
);
}
function _addedPropertyComparer (_object1Property,_object2Property) {
return !_object1Property && _object2Property ? {value:'added'} : undefined;
}
function _modifiedPropertyComparer (_object1Property,_object2Property) {
return (
_object1Property && _object2Property && _object1Property.value !== _object2Property.value
? {value:'modified'}
: undefined
);
}
function _removedPropertyComparer (_object1Property,_object2Property) {
return _object1Property && !_object2Property ? {value:'removed'} : undefined;
}
function _unmodifiedPropertyComparer (_object1Property,_object2Property) {
return (
_object1Property && _object2Property && _object1Property.value === _object2Property.value
? {value:'unchanged'}
: undefined
);
}
return Uize.Test.resolve ({
title:'Test for Uize.Data.Diff Module',
test:[
Uize.Test.requiredModulesTest ('Uize.Data.Diff'),
Uize.Test.staticMethodsTest ([
['Uize.Data.Diff.diff',[
/*** test the default property comparer ***/
['With the default property comparer, modified properties are marked by the value "modified"',
[
{foo:'bar'},
{foo:'BAR'}
],
{foo:'modified'}
],
['With the default property comparer, added properties are marked by the value "added"',
[
{},
{foo:'bar'}
],
{foo:'added'}
],
['With the default property comparer, removed properties are marked by the value "removed"',
[
{foo:'bar'},
{}
],
{foo:'removed'}
],
['With the default property comparer, unmodified properties are marked by the value "unchanged"',
[
{foo:'bar'},
{foo:'bar'}
],
{foo:'unchanged'}
],
['An arbitrarily complex data structure can be diff\'ed',
[
{
prop1:'foo',
prop2:'bar',
prop4:{
prop1:'foo',
prop2:'bar'
},
prop6:{
prop1:'foo',
prop2:'bar',
prop3:'baz'
}
},
{
prop1:'FOO',
prop3:'bar',
prop5:{
prop1:'foo',
prop2:'bar'
},
prop6:{
prop1:'foo',
prop2:'BAR',
prop4:'qux'
}
}
],
{
prop1:'modified',
prop2:'removed',
prop3:'added',
prop4:{
prop1:'removed',
prop2:'removed'
},
prop5:{
prop1:'added',
prop2:'added'
},
prop6:{
prop1:'unchanged',
prop2:'modified',
prop3:'removed',
prop4:'added'
}
}
],
/*** test array diffing ***/
['When the value of a property in both objects being compared is an array, then all the elements of the two array values will be compared',
[
{array:['foo','bar']},
{array:['foo','baz','qux']}
],
{array:['unchanged','modified','added']}
],
['When the value of a property is an array in the first object and missing in the second object, all the values from the array in the first object will appear to have been removed',
[
{array:['foo','bar','baz','qux']},
{}
],
{array:['removed','removed','removed','removed']}
],
['When the value of a property is an array in the second object and missing in the first object, all the values from the array in the second object will appear to have been added',
[
{},
{array:['foo','bar','baz','qux']}
],
{array:['added','added','added','added']}
],
/*** test the skeleton option ***/
['When the value false is specified for the optional skeleton option, then the returned comparison result will not contain empty nodes in which there are no property comparison values',
[
{
foo:{
bar:{},
baz:{
qux:[]
}
}
},
{
foo:{
BAR:{
BAZ:[]
}
},
QUX:{}
},
{skeleton:false}
],
{}
],
['When the value true is specified for the optional skeleton option, then the returned comparison result will at a minimum be a skeleton object that is the union of the structures of the two objects being compared',
[
{
foo:{
bar:{},
baz:{
qux:[]
}
}
},
{
foo:{
BAR:{
BAZ:[]
}
},
QUX:{}
},
null,
{skeleton:true}
],
{
foo:{
bar:{},
baz:{
qux:[]
},
BAR:{
BAZ:[]
}
},
QUX:{}
}
],
['When no value is specified for the optional skeleton option, it is defaulted to false and the skeleton behavior is disabled',
[
{
foo:{
bar:{},
baz:{
qux:[]
}
}
},
{
foo:{
BAR:{
BAZ:[]
}
},
QUX:{}
},
null,
{}
],
{}
],
/*** test the dual option ***/
['When the value false is specified for the optional dual option, then the recursion is driven by the first object',
[
{
foo:{
bar:{0:'fee',2:'FO',3:'fum'},
BAR:['fee','fi','fo'],
baz:{
qux:'nux',
dux:['bux','pux']
}
},
hello:5
},
{
foo:{
bar:['fee','fi','fo'],
BAR:{0:'fee',2:'FO',3:'fum'},
baz:'baz'
},
hello:{
thebird:['is','the','word']
}
},
null,
{dual:false,skeleton:true}
],
{
foo:{
bar:{0:'removed',2:'removed',3:'removed'},
BAR:['removed','removed','removed'],
baz:{
qux:'removed',
dux:['removed','removed']
}
},
hello:'modified'
}
],
['When a non-dual diff is performed, properties in object B whose values are not arrays when the values of the corresponding properties in object A are arrays are treated as being empty arrays for the purpose of the diff recursion',
[
{
prop1:['foo','bar'],
prop2:['foo','bar'],
prop3:['foo','bar'],
prop4:['foo','bar'],
prop5:['foo','bar'],
prop6:['foo','bar'],
prop7:['foo','bar']
},
{
prop1:42,
prop2:false,
prop3:'foo',
prop4:{foo:'bar'},
prop5:null,
prop6:/\d+/
},
null,
{dual:false}
],
{
prop1:['removed','removed'],
prop2:['removed','removed'],
prop3:['removed','removed'],
prop4:['removed','removed'],
prop5:['removed','removed'],
prop6:['removed','removed'],
prop7:['removed','removed']
}
],
['When a non-dual diff is performed, properties in object B whose values are not plain objects when the values of the corresponding properties in object A are plain objects are treated as being empty objects for the purpose of the diff recursion',
[
{
prop1:{foo:'FOO',bar:'BAR'},
prop2:{foo:'FOO',bar:'BAR'},
prop3:{foo:'FOO',bar:'BAR'},
prop4:{foo:'FOO',bar:'BAR'},
prop5:{foo:'FOO',bar:'BAR'},
prop6:{foo:'FOO',bar:'BAR'},
prop7:{foo:'FOO',bar:'BAR'}
},
{
prop1:42,
prop2:false,
prop3:'foo',
prop4:['foo','bar'],
prop5:null,
prop6:/\d+/
},
null,
{dual:false}
],
{
prop1:{foo:'removed',bar:'removed'},
prop2:{foo:'removed',bar:'removed'},
prop3:{foo:'removed',bar:'removed'},
prop4:{foo:'removed',bar:'removed'},
prop5:{foo:'removed',bar:'removed'},
prop6:{foo:'removed',bar:'removed'},
prop7:{foo:'removed',bar:'removed'}
}
],
['When performing a non-dual diff, properties in object B whose values are arrays or objects, when the values of the corresponding properties in object A are non-object types, are not recursed and are compared directly against the values in object A',
[
{
prop1:42,
prop2:false,
prop3:'foo',
prop4:undefined,
prop5:null,
prop6:/\d+/
},
{
prop1:{foo:'FOO',bar:'BAR'},
prop2:{foo:'FOO',bar:'BAR'},
prop3:{foo:'FOO',bar:'BAR'},
prop4:{foo:'FOO',bar:'BAR'},
prop5:{foo:'FOO',bar:'BAR'},
prop6:{foo:'FOO',bar:'BAR'}
},
null,
{dual:false}
],
{
prop1:'modified',
prop2:'modified',
prop3:'modified',
prop4:'modified',
prop5:'modified',
prop6:'modified'
}
],
['When performing a non-dual diff, properties that are present in objects in object B that are not present in the corresponding objects in object A are not iterated over',
[
{
foo:{foo:'FOO',bar:'BAR'}
},
{
foo:{foo:'FOO!',bar:'BAR',baz:'BAZ',qux:'QUX'}
},
null,
{dual:false}
],
{
foo:{foo:'modified',bar:'unchanged'}
}
],
['When performing a non-dual diff, elements that are present in arrays in object B that are not present in the corresponding arrays in object A are not iterated over',
[
{
foo:['FOO','BAR']
},
{
foo:['FOO!','BAR','BAZ','QUX']
},
null,
{dual:false}
],
{
foo:['modified','unchanged']
}
],
['When the value true is specified explicitly for the optional dual option, then the standard dual diff is performed',
[
{
prop1:{foo:'FOO',bar:'BAR'},
prop2:['FOO','BAR']
},
{
prop1:{foo:'FOO!',bar:'BAR',baz:'BAZ',qux:'QUX'},
prop2:['FOO!','BAR','BAZ','QUX']
},
null,
{dual:true}
],
{
prop1:{foo:'modified',bar:'unchanged',baz:'added',qux:'added'},
prop2:['modified','unchanged','added','added']
}
],
/*** test a custom added-or-modified property comparer ***/
['With a custom added-or-modified property comparer, modified properties are marked by their new value',
[
{foo:'bar'},
{foo:'BAR'},
_addedOrModifiedValuesPropertyComparer
],
{foo:'BAR'}
],
['With a custom added-or-modified property comparer, added properties are marked by their new value',
[
{},
{foo:'bar'},
_addedOrModifiedValuesPropertyComparer
],
{foo:'bar'}
],
['With a custom added-or-modified property comparer, removed properties are omitted from the result',
[
{foo:'bar'},
{},
_addedOrModifiedValuesPropertyComparer
],
{}
],
['With a custom added-or-modified property comparer, unmodified properties are omitted from the result',
[
{foo:'bar'},
{foo:'bar'},
_addedOrModifiedValuesPropertyComparer
],
{}
],
/*** test a custom added property comparer ***/
['With a custom added property comparer, modified properties are omitted from the result',
[
{foo:'bar'},
{foo:'BAR'},
_addedPropertyComparer
],
{}
],
['With a custom added property comparer, added properties are marked by the value "added"',
[
{},
{foo:'bar'},
_addedPropertyComparer
],
{foo:'added'}
],
['With a custom added property comparer, removed properties are omitted from the result',
[
{foo:'bar'},
{},
_addedPropertyComparer
],
{}
],
['With a custom added property comparer, unmodified properties are omitted from the result',
[
{foo:'bar'},
{foo:'bar'},
_addedPropertyComparer
],
{}
],
/*** test a custom modified property comparer ***/
['With a custom modified property comparer, modified properties are marked by the value "modified"',
[
{foo:'bar'},
{foo:'BAR'},
_modifiedPropertyComparer
],
{foo:'modified'}
],
['With a custom modified property comparer, added properties are omitted from the result',
[
{},
{foo:'bar'},
_modifiedPropertyComparer
],
{}
],
['With a custom modified property comparer, removed properties are omitted from the result',
[
{foo:'bar'},
{},
_modifiedPropertyComparer
],
{}
],
['With a custom modified property comparer, unmodified properties are omitted from the result',
[
{foo:'bar'},
{foo:'bar'},
_modifiedPropertyComparer
],
{}
],
/*** test a custom removed property comparer ***/
['With a custom removed property comparer, modified properties are omitted from the result',
[
{foo:'bar'},
{foo:'BAR'},
_removedPropertyComparer
],
{}
],
['With a custom removed property comparer, added properties are omitted from the result',
[
{},
{foo:'bar'},
_removedPropertyComparer
],
{}
],
['With a custom removed property comparer, removed properties are marked by the value "removed"',
[
{foo:'bar'},
{},
_removedPropertyComparer
],
{foo:'removed'}
],
['With a custom removed property comparer, unmodified properties are omitted from the result',
[
{foo:'bar'},
{foo:'bar'},
_removedPropertyComparer
],
{}
],
/*** test a custom unmodified property comparer ***/
['With a custom unmodified property comparer, modified properties are omitted from the result',
[
{foo:'bar'},
{foo:'BAR'},
_unmodifiedPropertyComparer
],
{}
],
['With a custom unmodified property comparer, added properties are omitted from the result',
[
{},
{foo:'bar'},
_unmodifiedPropertyComparer
],
{}
],
['With a custom unmodified property comparer, removed properties are omitted from the result',
[
{foo:'bar'},
{},
_unmodifiedPropertyComparer
],
{}
],
['With a custom unmodified property comparer, unmodified properties are marked by the value "unchanged"',
[
{foo:'bar'},
{foo:'bar'},
_unmodifiedPropertyComparer
],
{foo:'unchanged'}
],
/*** miscellaneous tests ***/
['The property info arguments that are provided to the property comparer function each contain a key property which indicates the name of the current property being compared',
[
{
foo:'FOO',
bar:{baz:'BAZ'}
},
{
qux:'QUX',
hello:{world:'WORLD'}
},
function (_object1PropertyInfo,_object2PropertyInfo) {
return {
value:[
_object1PropertyInfo && _object1PropertyInfo.key,
_object2PropertyInfo && _object2PropertyInfo.key
]
};
}
],
{
foo:['foo',undefined],
bar:{
baz:['baz',undefined]
},
qux:[undefined,'qux'],
hello:{
world:[undefined,'world']
}
}
],
{
title:'The property comparer function is passed a third argument, whose value is an array representing the path to the current property being compared',
test:function () {
var _comparedPropertiesPaths = [];
Uize.Data.Diff.diff (
{
prop1:'foo',
prop2:'bar',
prop4:{
prop1:'foo',
prop2:'bar'
},
prop6:{
prop1:'foo',
prop2:'bar',
prop3:'baz',
prop5:['foo','bar','baz']
}
},
{
prop1:'FOO',
prop3:'bar',
prop5:{
prop1:'foo',
prop2:'bar'
},
prop6:{
prop1:'foo',
prop2:'BAR',
prop4:'qux',
prop5:['foo']
},
prop7:['foo','bar']
},
function (_object1PropertyInfo,_object2PropertyInfo,_path) {
_comparedPropertiesPaths.push (_path.concat ());
}
);
return this.expect (
[
['prop1'],
['prop2'],
['prop4','prop1'],
['prop4','prop2'],
['prop6','prop1'],
['prop6','prop2'],
['prop6','prop3'],
['prop6','prop5',0],
['prop6','prop5',1],
['prop6','prop5',2],
['prop6','prop4'],
['prop3'],
['prop5','prop1'],
['prop5','prop2'],
['prop7',0],
['prop7',1]
],
_comparedPropertiesPaths
);
}
},
['The key property in the property profile object returned by a property comparer function is used to determine the name of the property added to the diff result',
[
{
leafNode1:'foo',
leafNode2:'bar',
nonLeadNode1:{
leafNode1:'foo',
leadNode2:'bar'
},
nonLeafNode2:{
leafNode1:'foo',
leafNode2:'bar',
nonLeafNode1:{
leafNode1:'foo',
leadNode2:'bar'
}
}
},
{},
function (_propertyProfile) {
_propertyProfile.key = _propertyProfile.key.toUpperCase ();
return _propertyProfile;
}
],
{
LEAFNODE1:'foo',
LEAFNODE2:'bar',
nonLeadNode1:{
LEAFNODE1:'foo',
LEADNODE2:'bar'
},
nonLeafNode2:{
LEAFNODE1:'foo',
LEAFNODE2:'bar',
nonLeafNode1:{
LEAFNODE1:'foo',
LEADNODE2:'bar'
}
}
}
],
['When a property in one object is a leaf node and the corresponding property in the other object is a non-leaf node, then the non-leaf node is recursed as if the leaf node was a non-leaf node',
[
{
foo:{hello:1,world:2},
bar:{hello:1,world:2},
baz:{hello:1,world:2},
FOO:'foo',
BAR:2,
BAZ:false
},
{
foo:'foo',
bar:2,
baz:false,
FOO:{hello:1,world:2},
BAR:{hello:1,world:2},
BAZ:{hello:1,world:2}
},
function (_object1PropertyInfo,_object2PropertyInfo) {
return _object1PropertyInfo || _object2PropertyInfo;
}
],
{
foo:{hello:1,world:2},
bar:{hello:1,world:2},
baz:{hello:1,world:2},
FOO:{hello:1,world:2},
BAR:{hello:1,world:2},
BAZ:{hello:1,world:2}
}
]
]]
])
]
});
}
});
//
koh5_pano
Drag mouse to navigate.
Navigation
- Left/Right Mouse drag: Changes camera heading.
- Up/Sown Mouse drag: Changes camera pitch.
- Scroll wheel: Changes camera field of view.
- I-Key: Displays Info panel with canvas size, image size and FPS.
17.Aug.2010, Martin Wengenmayer