2010-11-10 20:48:35 -05:00
|
|
|
/**
|
|
|
|
* Tests class module extend() method
|
|
|
|
*
|
2013-12-20 01:11:26 -05:00
|
|
|
* Copyright (C) 2010, 2011, 2013 Mike Gerwitz
|
2010-11-10 20:48:35 -05:00
|
|
|
*
|
2010-11-10 22:07:03 -05:00
|
|
|
* This file is part of ease.js.
|
2010-11-10 20:48:35 -05:00
|
|
|
*
|
2010-11-10 22:07:03 -05:00
|
|
|
* ease.js is free software: you can redistribute it and/or modify it under the
|
Relicensed under the GPLv3+
This project was originally LGPLv+-licensed to encourage its use in a community
that is largely copyleft-phobic. After further reflection, that was a mistake,
as adoption is not the important factor here---software freedom is.
When submitting ease.js to the GNU project, it was asked if I would be willing
to relicense it under the GPLv3+; I agreed happily, because there is no reason
why we should provide proprietary software any sort of edge. Indeed, proprietary
JavaScript is a huge problem since it is automatically downloaded on the user's
PC generally without them even knowing, and is a current focus for the FSF. As
such, to remain firm in our stance against proprietary JavaScript, relicensing
made the most sense for GNU.
This is likely to upset current users of ease.js. I am not sure of their
number---I have only seen download counts periodically on npmjs.org---but I know
there are at least a small number. These users are free to continue using the
previous LGPL'd releases, but with the understanding that there will be no
further maintenance (not even bug fixes). If possible, users should use the
GPL-licensed versions and release their software as free software.
Here comes GNU ease.js.
2013-12-20 01:00:35 -05:00
|
|
|
* terms of the GNU General Public License as published by the Free Software
|
|
|
|
* Foundation, either version 3 of the License, or (at your option) any later
|
|
|
|
* version.
|
2010-11-10 20:48:35 -05:00
|
|
|
*
|
2010-11-10 22:07:03 -05:00
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
Relicensed under the GPLv3+
This project was originally LGPLv+-licensed to encourage its use in a community
that is largely copyleft-phobic. After further reflection, that was a mistake,
as adoption is not the important factor here---software freedom is.
When submitting ease.js to the GNU project, it was asked if I would be willing
to relicense it under the GPLv3+; I agreed happily, because there is no reason
why we should provide proprietary software any sort of edge. Indeed, proprietary
JavaScript is a huge problem since it is automatically downloaded on the user's
PC generally without them even knowing, and is a current focus for the FSF. As
such, to remain firm in our stance against proprietary JavaScript, relicensing
made the most sense for GNU.
This is likely to upset current users of ease.js. I am not sure of their
number---I have only seen download counts periodically on npmjs.org---but I know
there are at least a small number. These users are free to continue using the
previous LGPL'd releases, but with the understanding that there will be no
further maintenance (not even bug fixes). If possible, users should use the
GPL-licensed versions and release their software as free software.
Here comes GNU ease.js.
2013-12-20 01:00:35 -05:00
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
* more details.
|
2010-11-10 22:07:03 -05:00
|
|
|
*
|
Relicensed under the GPLv3+
This project was originally LGPLv+-licensed to encourage its use in a community
that is largely copyleft-phobic. After further reflection, that was a mistake,
as adoption is not the important factor here---software freedom is.
When submitting ease.js to the GNU project, it was asked if I would be willing
to relicense it under the GPLv3+; I agreed happily, because there is no reason
why we should provide proprietary software any sort of edge. Indeed, proprietary
JavaScript is a huge problem since it is automatically downloaded on the user's
PC generally without them even knowing, and is a current focus for the FSF. As
such, to remain firm in our stance against proprietary JavaScript, relicensing
made the most sense for GNU.
This is likely to upset current users of ease.js. I am not sure of their
number---I have only seen download counts periodically on npmjs.org---but I know
there are at least a small number. These users are free to continue using the
previous LGPL'd releases, but with the understanding that there will be no
further maintenance (not even bug fixes). If possible, users should use the
GPL-licensed versions and release their software as free software.
Here comes GNU ease.js.
2013-12-20 01:00:35 -05:00
|
|
|
* You should have received a copy of the GNU General Public License along with
|
|
|
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
2010-11-10 20:48:35 -05:00
|
|
|
*
|
|
|
|
* @author Mike Gerwitz
|
|
|
|
*/
|
|
|
|
|
2010-12-21 23:25:12 -05:00
|
|
|
var common = require( './common' ),
|
|
|
|
assert = require( 'assert' ),
|
|
|
|
Class = common.require( 'class' );
|
2010-11-10 20:48:35 -05:00
|
|
|
|
2010-11-10 21:10:31 -05:00
|
|
|
var foo_props = {
|
|
|
|
one: 1,
|
|
|
|
two: 2,
|
|
|
|
},
|
2010-11-10 20:48:35 -05:00
|
|
|
|
2011-03-03 19:43:20 -05:00
|
|
|
// there are two different means of extending; we want to test them both
|
|
|
|
classes = [
|
|
|
|
Class.extend( foo_props ),
|
|
|
|
Class( foo_props ),
|
|
|
|
],
|
2010-11-10 21:10:31 -05:00
|
|
|
|
2011-12-10 11:06:34 -05:00
|
|
|
class_count = classes.length,
|
2011-03-03 19:43:20 -05:00
|
|
|
|
|
|
|
// will hold the class being tested
|
|
|
|
Foo = null
|
|
|
|
;
|
2010-11-10 20:48:35 -05:00
|
|
|
|
|
|
|
|
2011-03-03 19:43:20 -05:00
|
|
|
// Run all tests for both. This will ensure that, regardless of how the class is
|
|
|
|
// created, it operates as it should. Fortunately, these tests are fairly quick.
|
|
|
|
for ( var i = 0; i < class_count; i++ )
|
2010-11-10 21:10:31 -05:00
|
|
|
{
|
2011-03-03 19:43:20 -05:00
|
|
|
Foo = classes[ i ];
|
|
|
|
|
|
|
|
assert.ok(
|
|
|
|
( Foo.extend instanceof Function ),
|
|
|
|
"Created class contains extend method"
|
2010-11-10 21:10:31 -05:00
|
|
|
);
|
|
|
|
|
2011-03-03 19:43:20 -05:00
|
|
|
var sub_props = {
|
|
|
|
three: 3,
|
|
|
|
four: 4,
|
|
|
|
},
|
2011-03-03 23:29:20 -05:00
|
|
|
|
|
|
|
SubFoo = Foo.extend( sub_props ),
|
|
|
|
sub_foo = SubFoo()
|
|
|
|
;
|
2011-03-03 19:43:20 -05:00
|
|
|
|
|
|
|
assert.ok(
|
|
|
|
( SubFoo instanceof Object ),
|
|
|
|
"Subtype is returned as an object"
|
2010-11-10 21:10:31 -05:00
|
|
|
);
|
2010-11-10 21:39:09 -05:00
|
|
|
|
2011-03-03 19:43:20 -05:00
|
|
|
// ensure properties were inherited from supertype
|
|
|
|
for ( var prop in foo_props )
|
|
|
|
{
|
|
|
|
assert.equal(
|
|
|
|
foo_props[ prop ],
|
|
|
|
SubFoo.prototype[ prop ],
|
|
|
|
"Subtype inherits parent properties: " + prop
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// and ensure that the subtype's properties were included
|
|
|
|
for ( var prop in sub_props )
|
|
|
|
{
|
|
|
|
assert.equal(
|
|
|
|
sub_props[ prop ],
|
2011-03-03 23:29:20 -05:00
|
|
|
sub_foo[ prop ],
|
2011-03-03 19:43:20 -05:00
|
|
|
"Subtype contains its own properties: " + prop
|
|
|
|
);
|
|
|
|
}
|
2010-12-29 21:45:33 -05:00
|
|
|
|
2010-11-11 21:02:09 -05:00
|
|
|
|
2011-03-03 19:43:20 -05:00
|
|
|
var sub_instance = new SubFoo();
|
2010-11-11 21:02:09 -05:00
|
|
|
|
2011-03-03 19:43:20 -05:00
|
|
|
assert.ok(
|
|
|
|
( sub_instance instanceof Foo ),
|
|
|
|
"Subtypes are considered to be instances of their supertypes " +
|
|
|
|
"(via instanceof operator)"
|
|
|
|
);
|
2010-11-11 21:02:09 -05:00
|
|
|
|
2011-03-03 19:43:20 -05:00
|
|
|
assert.ok(
|
|
|
|
sub_instance.isInstanceOf( SubFoo ),
|
|
|
|
"Subtypes are considered to be instances of their supertypes (via " +
|
|
|
|
"isInstanceOf method)"
|
|
|
|
);
|
2010-11-11 21:02:09 -05:00
|
|
|
|
|
|
|
|
2011-03-03 19:43:20 -05:00
|
|
|
// Foo
|
|
|
|
// |
|
|
|
|
// SubFoo
|
|
|
|
// / \
|
|
|
|
// SubSubFoo SubSubFoo2
|
|
|
|
//
|
|
|
|
var SubSubFoo = SubFoo.extend(),
|
|
|
|
SubSubFoo2 = SubFoo.extend(),
|
2010-11-11 21:02:09 -05:00
|
|
|
|
2011-03-03 19:43:20 -05:00
|
|
|
sub_sub_instance = new SubSubFoo(),
|
|
|
|
sub_sub2_instance = new SubSubFoo2();
|
2010-12-07 20:24:51 -05:00
|
|
|
|
2011-03-03 19:43:20 -05:00
|
|
|
assert.ok(
|
|
|
|
( ( sub_sub_instance instanceof Foo )
|
|
|
|
&& sub_sub_instance.isInstanceOf( Foo )
|
|
|
|
),
|
|
|
|
"Sub-subtypes should be instances of their super-supertype"
|
|
|
|
);
|
|
|
|
|
|
|
|
assert.ok(
|
|
|
|
( !( sub_instance instanceof SubSubFoo )
|
|
|
|
&& !( sub_instance.isInstanceOf( SubSubFoo ) )
|
|
|
|
),
|
|
|
|
"Supertypes should not be considered instances of their subtypes"
|
|
|
|
);
|
|
|
|
|
|
|
|
assert.ok(
|
|
|
|
( !( sub_sub2_instance instanceof SubSubFoo )
|
|
|
|
&& !( sub_sub2_instance.isInstanceOf( SubSubFoo ) )
|
|
|
|
),
|
|
|
|
"Subtypes should not be considered instances of their siblings"
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// to test inheritance of classes that were not previously created via the
|
|
|
|
// Class.extend() method
|
|
|
|
var OtherClass = function() {};
|
|
|
|
OtherClass.prototype =
|
2010-12-07 20:24:51 -05:00
|
|
|
{
|
2011-03-03 19:43:20 -05:00
|
|
|
foo: 'bla',
|
|
|
|
};
|
|
|
|
|
|
|
|
var SubOther = Class.extend( OtherClass,
|
2010-12-07 20:24:51 -05:00
|
|
|
{
|
2011-03-03 19:43:20 -05:00
|
|
|
newFoo: 2,
|
2010-12-07 20:24:51 -05:00
|
|
|
});
|
|
|
|
|
2010-12-16 23:18:30 -05:00
|
|
|
|
2011-03-03 19:43:20 -05:00
|
|
|
assert.equal(
|
|
|
|
SubOther.prototype.foo,
|
|
|
|
OtherClass.prototype.foo,
|
|
|
|
"Prototype of existing class should be copied to subclass"
|
|
|
|
);
|
2010-12-16 23:37:18 -05:00
|
|
|
|
2011-03-03 19:43:20 -05:00
|
|
|
assert.notEqual(
|
2011-03-03 23:29:20 -05:00
|
|
|
SubOther().newFoo,
|
2011-03-03 19:43:20 -05:00
|
|
|
undefined,
|
|
|
|
"Subtype should contain extended members"
|
|
|
|
);
|
2010-12-16 23:37:18 -05:00
|
|
|
|
|
|
|
|
2011-12-04 19:26:53 -05:00
|
|
|
assert['throws']( function()
|
2011-03-03 19:43:20 -05:00
|
|
|
{
|
|
|
|
Class.extend( OtherClass,
|
|
|
|
{
|
|
|
|
foo: function() {},
|
|
|
|
});
|
|
|
|
}, TypeError, "Cannot override property with a method" );
|
2010-12-16 23:37:18 -05:00
|
|
|
|
|
|
|
|
2011-03-03 19:43:20 -05:00
|
|
|
var AnotherFoo = Class.extend(
|
2010-12-16 23:55:56 -05:00
|
|
|
{
|
2011-03-03 19:43:20 -05:00
|
|
|
arr: [],
|
|
|
|
obj: {},
|
2010-12-16 23:55:56 -05:00
|
|
|
});
|
|
|
|
|
2011-03-03 19:43:20 -05:00
|
|
|
var Obj1 = new AnotherFoo(),
|
|
|
|
Obj2 = new AnotherFoo();
|
2010-12-17 00:01:22 -05:00
|
|
|
|
2011-03-03 19:43:20 -05:00
|
|
|
Obj1.arr.push( 'one' );
|
|
|
|
Obj2.arr.push( 'two' );
|
2010-12-17 00:01:22 -05:00
|
|
|
|
2011-03-03 19:43:20 -05:00
|
|
|
Obj1.obj.a = true;
|
|
|
|
Obj2.obj.b = true;
|
|
|
|
|
|
|
|
// to ensure we're not getting/setting values of the prototype (=== can also be
|
|
|
|
// used to test for references, but this test demonstrates the functionality
|
|
|
|
// that we're looking to ensure)
|
|
|
|
assert.ok(
|
|
|
|
( ( Obj1.arr[ 0 ] === 'one' ) && ( Obj2.arr[ 0 ] === 'two' ) ),
|
|
|
|
"Multiple instances of the same class do not share array references"
|
|
|
|
);
|
|
|
|
|
|
|
|
assert.ok(
|
|
|
|
( ( ( Obj1.obj.a === true ) && ( Obj1.obj.b === undefined ) )
|
|
|
|
&& ( ( Obj2.obj.a === undefined ) && ( Obj2.obj.b === true ) )
|
|
|
|
),
|
|
|
|
"Multiple instances of the same class do not share object references"
|
|
|
|
);
|
|
|
|
|
|
|
|
var arr_val = 1;
|
|
|
|
var SubAnotherFoo = AnotherFoo.extend(
|
2010-12-16 23:55:56 -05:00
|
|
|
{
|
2011-03-03 19:43:20 -05:00
|
|
|
arr: [ arr_val ],
|
2010-12-16 23:55:56 -05:00
|
|
|
});
|
|
|
|
|
2011-03-03 19:43:20 -05:00
|
|
|
var SubObj1 = new SubAnotherFoo(),
|
|
|
|
SubObj2 = new SubAnotherFoo();
|
2010-12-17 00:01:22 -05:00
|
|
|
|
2011-03-03 19:43:20 -05:00
|
|
|
assert.ok(
|
|
|
|
( ( SubObj1.arr !== SubObj2.arr ) && ( SubObj1.obj !== SubObj2.obj ) ),
|
|
|
|
"Instances of subtypes do not share property references"
|
|
|
|
);
|
2010-12-17 00:01:22 -05:00
|
|
|
|
2011-03-03 19:43:20 -05:00
|
|
|
assert.ok(
|
|
|
|
( ( SubObj1.arr[ 0 ] === arr_val ) && ( SubObj2.arr[ 0 ] === arr_val ) ),
|
|
|
|
"Subtypes can override parent property values"
|
|
|
|
);
|
|
|
|
|
2011-12-04 19:26:53 -05:00
|
|
|
assert['throws']( function()
|
2011-03-03 19:43:20 -05:00
|
|
|
{
|
|
|
|
Class.extend(
|
|
|
|
{
|
|
|
|
__initProps: function() {},
|
|
|
|
});
|
|
|
|
}, Error, "__initProps() cannot be declared (internal method)" );
|
|
|
|
|
|
|
|
|
|
|
|
var SubSubAnotherFoo = AnotherFoo.extend(),
|
|
|
|
SubSubObj1 = new SubSubAnotherFoo(),
|
|
|
|
SubSubObj2 = new SubSubAnotherFoo();
|
|
|
|
|
|
|
|
// to ensure the effect is recursive
|
|
|
|
assert.ok(
|
|
|
|
( ( SubSubObj1.arr !== SubSubObj2.arr )
|
|
|
|
&& ( SubSubObj1.obj !== SubSubObj2.obj )
|
|
|
|
),
|
|
|
|
"Instances of subtypes do not share property references"
|
|
|
|
);
|
|
|
|
}
|
2010-12-17 00:01:22 -05:00
|
|
|
|
2011-01-17 20:20:39 -05:00
|
|
|
|
2011-03-03 19:43:20 -05:00
|
|
|
( function testInvokingClassModuleRequiresObjectAsArgumentIfCreating()
|
2011-01-17 20:20:39 -05:00
|
|
|
{
|
2011-12-04 19:26:53 -05:00
|
|
|
assert['throws']( function()
|
2011-03-03 19:43:20 -05:00
|
|
|
{
|
|
|
|
Class( 'moo' );
|
|
|
|
Class( 5 );
|
|
|
|
Class( false );
|
|
|
|
Class();
|
|
|
|
},
|
|
|
|
TypeError,
|
|
|
|
"Invoking class module requires object as argument if extending " +
|
|
|
|
"from base class"
|
2011-01-17 20:20:39 -05:00
|
|
|
);
|
2011-03-03 19:43:20 -05:00
|
|
|
|
|
|
|
var args = [ {}, 'one', 'two', 'three' ];
|
|
|
|
|
|
|
|
// we must only provide one argument if the first argument is an object (the
|
|
|
|
// class definition)
|
|
|
|
try
|
|
|
|
{
|
|
|
|
Class.apply( null, args );
|
|
|
|
|
|
|
|
// if all goes well, we don't get to this line
|
|
|
|
assert.fail(
|
|
|
|
"Only one argument for class definitions is permitted"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
catch ( e )
|
|
|
|
{
|
|
|
|
assert.notEqual(
|
2011-03-06 10:37:20 -05:00
|
|
|
e.message.match( args.length + ' given' ),
|
2011-03-03 19:43:20 -05:00
|
|
|
null,
|
|
|
|
"Class invocation should give argument count on error"
|
|
|
|
);
|
|
|
|
}
|
2011-01-17 20:20:39 -05:00
|
|
|
} )();
|
|
|
|
|
2011-03-05 23:11:13 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* We provide a useful default toString() method, but one may wish to override
|
|
|
|
* it
|
|
|
|
*/
|
|
|
|
( function testCanOverrideToStringMethod()
|
|
|
|
{
|
|
|
|
var str = 'foomookittypoo',
|
|
|
|
result = ''
|
|
|
|
;
|
|
|
|
|
2011-03-06 12:38:31 -05:00
|
|
|
result = Class( 'FooToStr',
|
2011-03-05 23:11:13 -05:00
|
|
|
{
|
|
|
|
toString: function()
|
|
|
|
{
|
|
|
|
return str;
|
2011-03-06 12:38:31 -05:00
|
|
|
},
|
|
|
|
bla: function() {},
|
2011-03-05 23:11:13 -05:00
|
|
|
})().toString();
|
|
|
|
|
|
|
|
assert.equal(
|
|
|
|
result,
|
|
|
|
str,
|
|
|
|
"Can override default toString() method of class"
|
|
|
|
);
|
|
|
|
} )();
|
|
|
|
|
2011-03-19 00:48:02 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* In ease.js's initial design, keywords were not included. This meant that
|
|
|
|
* duplicate member definitions were not possible - it'd throw a parse error.
|
|
|
|
* However, with keywords, it is now possible to redeclare a member with the
|
|
|
|
* same name in the same class definition. Since this doesn't make much sense,
|
|
|
|
* we must disallow it.
|
|
|
|
*/
|
|
|
|
( function testCannotProvideDuplicateMemberDefintions()
|
|
|
|
{
|
2011-12-04 19:26:53 -05:00
|
|
|
assert['throws']( function()
|
2011-03-19 00:48:02 -04:00
|
|
|
{
|
|
|
|
Class(
|
|
|
|
{
|
|
|
|
// declare as protected first so that we won't get a visibility
|
|
|
|
// de-escalation error with the below re-definition
|
|
|
|
'protected foo': '',
|
|
|
|
|
|
|
|
// should fail; redefinition
|
|
|
|
'public foo': '',
|
|
|
|
} );
|
|
|
|
}, Error, "Cannot redeclare property in same class definition" );
|
|
|
|
|
2011-12-04 19:26:53 -05:00
|
|
|
assert['throws']( function()
|
2011-03-19 00:48:02 -04:00
|
|
|
{
|
|
|
|
Class(
|
|
|
|
{
|
|
|
|
// declare as protected first so that we won't get a visibility
|
|
|
|
// de-escalation error with the below re-definition
|
|
|
|
'protected foo': function() {},
|
|
|
|
|
|
|
|
// should fail; redefinition
|
|
|
|
'public foo': function() {},
|
|
|
|
} );
|
|
|
|
}, Error, "Cannot redeclare method in same class definition" );
|
|
|
|
} )();
|
|
|
|
|
2011-05-10 23:21:12 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* To understand this test, one must understand how "inheritance" works
|
|
|
|
* with prototypes. We must create a new instance of the ctor (class) and add
|
|
|
|
* that instance to the prototype chain (if we added an un-instantiated
|
|
|
|
* constructor, then the members in the prototype would be accessible only
|
|
|
|
* though ctor.prototype). Therefore, when we instantiate this class for use in
|
|
|
|
* the prototype, we must ensure the constructor is not invoked, since our
|
|
|
|
* intent is not to create a new instance of the class.
|
|
|
|
*/
|
|
|
|
( function testConstructorShouldNotBeCalledWhenExtendingClass()
|
|
|
|
{
|
|
|
|
var called = false,
|
|
|
|
Foo = Class( {
|
|
|
|
'public __construct': function()
|
|
|
|
{
|
|
|
|
called = true;
|
|
|
|
}
|
|
|
|
} ).extend( {} );
|
|
|
|
|
|
|
|
assert.equal( called, false,
|
|
|
|
"Constructor should not be called when extending a class"
|
|
|
|
);
|
|
|
|
} )();
|
|
|
|
|
2011-05-22 21:54:41 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Previously, when attempting to extend from an invalid supertype, you'd get a
|
|
|
|
* CALL_NON_FUNCTION_AS_CONSTRUCTOR error, which is not very helpful to someone
|
|
|
|
* who is not familiar with the ease.js internals. Let's provide a more useful
|
|
|
|
* error that clearly states what's going on.
|
|
|
|
*/
|
|
|
|
( function testExtendingFromNonCtorOrClassProvidesUsefulError()
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
// invalid supertype
|
|
|
|
Class.extend( 'oops', {} );
|
|
|
|
}
|
|
|
|
catch ( e )
|
|
|
|
{
|
|
|
|
assert.ok( e.message.search( 'extend from' ),
|
|
|
|
"Error message for extending from non-ctor or class makes sense"
|
|
|
|
);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert.fail(
|
|
|
|
"Attempting to extend from non-ctor or class should throw exception"
|
|
|
|
);
|
|
|
|
} )();
|
|
|
|
|
2011-08-04 00:44:20 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Only virtual methods may be overridden.
|
|
|
|
*/
|
|
|
|
( function testCannotOverrideNonVirtualMethod()
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
var Foo = Class(
|
|
|
|
{
|
|
|
|
// non-virtual
|
|
|
|
'public foo': function() {},
|
|
|
|
} ),
|
|
|
|
|
|
|
|
SubFoo = Foo.extend(
|
|
|
|
{
|
|
|
|
// should fail (cannot override non-virtual method)
|
|
|
|
'override public foo': function() {},
|
|
|
|
} );
|
|
|
|
}
|
|
|
|
catch ( e )
|
|
|
|
{
|
|
|
|
assert.ok( e.message.search( 'foo' ),
|
|
|
|
"Non-virtual override error message should contain name of method"
|
|
|
|
);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert.fail( "Should not be permitted to override non-virtual method" );
|
|
|
|
} )();
|
|
|
|
|
2011-12-15 22:58:23 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* If we attempt to extend an object (rather than a constructor), we should
|
|
|
|
* simply use that as the prototype directly rather than attempting to
|
|
|
|
* instantiate it.
|
|
|
|
*/
|
|
|
|
( function testExtendingObjectWillNotAttemptInstantiation()
|
|
|
|
{
|
|
|
|
var obj = { foo: 'bar' };
|
|
|
|
|
|
|
|
assert.equal( obj.foo, Class.extend( obj, {} )().foo,
|
|
|
|
'Should be able to use object as prototype'
|
|
|
|
);
|
|
|
|
} )();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* It only makes sense to extend from an object or function (constructor, more
|
|
|
|
* specifically)
|
|
|
|
*
|
|
|
|
* We could also test to ensure that the return value of the constructor is an
|
|
|
|
* object, but that is unnecessary for the time being.
|
|
|
|
*/
|
|
|
|
( function testWillThrowExceptionIfNonObjectOrCtorIsProvided()
|
|
|
|
{
|
|
|
|
assert['throws']( function()
|
|
|
|
{
|
|
|
|
Class.extend( 'foo', {} );
|
|
|
|
}, TypeError, 'Should not be able to extend from non-object or non-ctor' );
|
|
|
|
} )();
|
|
|
|
|