2011-03-03 22:33:18 -05:00
|
|
|
/**
|
|
|
|
* Tests class naming
|
|
|
|
*
|
2013-12-20 01:11:26 -05:00
|
|
|
* Copyright (C) 2011, 2013 Mike Gerwitz
|
2011-03-03 22:33:18 -05:00
|
|
|
*
|
|
|
|
* This file is part of ease.js.
|
|
|
|
*
|
|
|
|
* 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.
|
2011-03-03 22:33:18 -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.
|
2011-03-03 22:33:18 -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/>.
|
2011-03-03 22:33:18 -05:00
|
|
|
*
|
|
|
|
* @author Mike Gerwitz
|
|
|
|
*/
|
|
|
|
|
|
|
|
var common = require( './common' ),
|
|
|
|
assert = require( 'assert' ),
|
2011-03-05 03:22:45 -05:00
|
|
|
|
2011-05-22 13:57:56 -04:00
|
|
|
Class = common.require( 'class' ),
|
|
|
|
AbstractClass = common.require( 'class_abstract' ),
|
|
|
|
Interface = common.require( 'interface' )
|
2011-03-03 22:33:18 -05:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Classes may be named by passing the name as the first argument to the module
|
|
|
|
*/
|
|
|
|
( function testClassAcceptsName()
|
|
|
|
{
|
|
|
|
assert.doesNotThrow( function()
|
|
|
|
{
|
|
|
|
var cls = Class( 'Foo', {} );
|
|
|
|
|
|
|
|
assert.equal(
|
|
|
|
Class.isClass( cls ),
|
|
|
|
true,
|
|
|
|
"Class defined with name is returned as a valid class"
|
|
|
|
);
|
|
|
|
}, Error, "Class accepts name" );
|
2011-03-05 12:56:14 -05:00
|
|
|
} )();
|
|
|
|
|
2011-03-03 22:33:18 -05:00
|
|
|
|
2011-03-05 12:56:14 -05:00
|
|
|
/**
|
|
|
|
* The class definition must be an object, which is equivalent to the class
|
|
|
|
* body
|
|
|
|
*/
|
|
|
|
( function testNamedClassDefinitionRequiresThatDefinitionBeAnObject()
|
|
|
|
{
|
|
|
|
var name = 'Foo';
|
|
|
|
|
|
|
|
try
|
2011-03-03 22:33:18 -05:00
|
|
|
{
|
2011-03-05 12:56:14 -05:00
|
|
|
Class( name, 'Bar' );
|
|
|
|
|
|
|
|
// if all goes well, we'll never get to this point
|
|
|
|
assert.fail( "Second argument to named class must be the definition" );
|
|
|
|
}
|
|
|
|
catch ( e )
|
|
|
|
{
|
|
|
|
assert.notEqual(
|
2011-03-06 10:37:20 -05:00
|
|
|
e.message.match( name ),
|
2011-03-05 12:56:14 -05:00
|
|
|
null,
|
|
|
|
"Class definition argument count error string contains class name"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
} )();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Extraneous arguments likely indicate a misunderstanding of the API
|
|
|
|
*/
|
|
|
|
( function testNamedClassDefinitionIsStrictOnArgumentCount()
|
|
|
|
{
|
|
|
|
var name = 'Foo',
|
|
|
|
args = [ name, {}, 'extra' ]
|
|
|
|
;
|
2011-03-04 16:36:15 -05:00
|
|
|
|
|
|
|
// we should be permitted only two arguments
|
|
|
|
try
|
|
|
|
{
|
|
|
|
Class.apply( null, args );
|
|
|
|
|
|
|
|
// we should not get to this line (an exception should be thrown due to
|
|
|
|
// too many arguments)
|
|
|
|
assert.fail(
|
|
|
|
"Should accept only two arguments when creating named class"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
catch ( e )
|
|
|
|
{
|
2011-03-06 10:37:20 -05:00
|
|
|
var errstr = e.message;
|
2011-03-05 12:56:14 -05:00
|
|
|
|
|
|
|
assert.notEqual(
|
|
|
|
errstr.match( name ),
|
|
|
|
null,
|
|
|
|
"Named class error should provide name of class"
|
|
|
|
);
|
|
|
|
|
2011-03-04 16:36:15 -05:00
|
|
|
assert.notEqual(
|
2011-03-05 12:56:14 -05:00
|
|
|
errstr.match( args.length + ' given' ),
|
2011-03-04 16:36:15 -05:00
|
|
|
null,
|
|
|
|
"Named class error should provide number of given arguments"
|
|
|
|
);
|
|
|
|
}
|
2011-03-03 22:33:18 -05:00
|
|
|
} )();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* By default, anonymous classes should just state that they are a class when
|
|
|
|
* they are converted to a string
|
|
|
|
*/
|
|
|
|
( function testConvertingAnonymousClassToStringYieldsClassString()
|
|
|
|
{
|
|
|
|
// concrete
|
|
|
|
assert.equal(
|
|
|
|
Class( {} ).toString(),
|
2011-03-14 18:16:53 -04:00
|
|
|
'(Class)',
|
2011-03-03 22:33:18 -05:00
|
|
|
"Converting anonymous class to string yields class string"
|
|
|
|
);
|
|
|
|
|
|
|
|
// abstract
|
|
|
|
assert.equal(
|
2011-05-22 13:57:56 -04:00
|
|
|
AbstractClass( { 'abstract foo': [] } ).toString(),
|
2011-03-14 18:16:53 -04:00
|
|
|
'(AbstractClass)',
|
2011-03-03 22:33:18 -05:00
|
|
|
"Converting abstract anonymous class to string yields class string"
|
|
|
|
);
|
|
|
|
} )();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the class is named, then the name should be presented when it is converted
|
|
|
|
* to a string
|
|
|
|
*/
|
|
|
|
( function testConvertingNamedClassToStringYieldsClassStringContainingName()
|
|
|
|
{
|
|
|
|
var name = 'Foo';
|
|
|
|
|
|
|
|
// concrete
|
|
|
|
assert.equal(
|
|
|
|
Class( name, {} ).toString(),
|
2011-03-14 18:16:53 -04:00
|
|
|
name,
|
2011-03-03 22:33:18 -05:00
|
|
|
"Converting named class to string yields string with name of class"
|
|
|
|
);
|
|
|
|
|
|
|
|
// abstract
|
|
|
|
assert.equal(
|
2011-05-22 13:57:56 -04:00
|
|
|
AbstractClass( name, { 'abstract foo': [] } ).toString(),
|
2011-03-14 18:16:53 -04:00
|
|
|
name,
|
2011-03-03 22:33:18 -05:00
|
|
|
"Converting abstract named class to string yields string with name " +
|
|
|
|
"of class"
|
|
|
|
);
|
|
|
|
} )();
|
|
|
|
|
2011-03-03 22:53:20 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Class instances are displayed differently than uninstantiated classes.
|
|
|
|
* Mainly, they output that they are an object, in addition to the class name.
|
|
|
|
*/
|
|
|
|
( function testConvertingClassInstanceToStringYieldsInstanceString()
|
|
|
|
{
|
|
|
|
var name = 'Foo',
|
|
|
|
|
|
|
|
anon = Class( {} )(),
|
|
|
|
named = Class( name, {} )()
|
|
|
|
;
|
|
|
|
|
|
|
|
// anonymous
|
|
|
|
assert.equal(
|
|
|
|
anon.toString(),
|
2011-03-14 18:16:53 -04:00
|
|
|
'#<anonymous>',
|
2011-03-03 22:53:20 -05:00
|
|
|
"Converting anonymous class instance to string yields string " +
|
|
|
|
"indiciating that the class is anonymous"
|
|
|
|
);
|
|
|
|
|
|
|
|
// named
|
|
|
|
assert.equal(
|
|
|
|
named.toString(),
|
2011-03-14 18:16:53 -04:00
|
|
|
'#<' + name + '>',
|
2011-03-03 22:53:20 -05:00
|
|
|
"Converting named class instance to string yields string with name " +
|
|
|
|
"of class"
|
|
|
|
);
|
|
|
|
} )();
|
|
|
|
|
2011-03-05 00:33:47 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* In order to accommodate syntax such as extending classes, ease.js supports
|
|
|
|
* staging class names. This will return an object that operates exactly like
|
|
|
|
* the normal Class module, but will result in a named class once the class is
|
|
|
|
* created.
|
|
|
|
*/
|
|
|
|
( function testCanCreateNamedClassUsingStagingMethod()
|
|
|
|
{
|
2011-03-05 03:22:45 -05:00
|
|
|
var name = 'Foo',
|
2011-12-10 11:06:34 -05:00
|
|
|
named = Class( name ).extend( {} ),
|
|
|
|
namedi = Class( name ).implement( Interface( {} ) ).extend( {} ),
|
2011-03-16 18:18:33 -04:00
|
|
|
|
|
|
|
// we should also be able to extend classes in this manner
|
|
|
|
namede = Class( name ).implement( Interface( {} ) ).extend( named, {} )
|
2011-03-05 00:33:47 -05:00
|
|
|
;
|
|
|
|
|
|
|
|
// ensure what was returned is a valid class
|
|
|
|
assert.equal(
|
|
|
|
Class.isClass( named ),
|
|
|
|
true,
|
|
|
|
"Named class generated via staging method is considered to be a " +
|
|
|
|
"valid class"
|
|
|
|
);
|
|
|
|
|
|
|
|
// was the name set?
|
|
|
|
assert.equal(
|
|
|
|
named.toString(),
|
2011-03-14 18:16:53 -04:00
|
|
|
name,
|
2011-03-05 00:33:47 -05:00
|
|
|
"Name is set on named clas via staging method"
|
|
|
|
);
|
2011-03-05 03:22:45 -05:00
|
|
|
|
|
|
|
|
|
|
|
// we should also be able to implement interfaces
|
|
|
|
assert.equal(
|
|
|
|
Class.isClass( namedi ),
|
|
|
|
true,
|
|
|
|
"Named class generated via staging method, implementing an " +
|
|
|
|
"interface, is considered to be a valid class"
|
|
|
|
);
|
|
|
|
|
|
|
|
assert.equal(
|
|
|
|
namedi.toString(),
|
2011-03-14 18:16:53 -04:00
|
|
|
name,
|
2011-03-05 03:22:45 -05:00
|
|
|
"Name is set on named class via staging method when implementing"
|
|
|
|
);
|
2011-03-16 18:18:33 -04:00
|
|
|
|
|
|
|
|
|
|
|
// we should be able to extend existing classes
|
|
|
|
assert.equal(
|
|
|
|
Class.isClass( namede ),
|
|
|
|
true,
|
|
|
|
"Named class generated via staging method, implementing an " +
|
|
|
|
"interface, and extending an existing class is considered " +
|
|
|
|
"to be a valid class"
|
|
|
|
);
|
|
|
|
|
|
|
|
assert.equal(
|
|
|
|
Class.isInstanceOf( named, namede() ),
|
|
|
|
true,
|
|
|
|
"Named class extending base class is instance of the base class"
|
|
|
|
);
|
|
|
|
|
|
|
|
assert.equal(
|
|
|
|
namede.toString(),
|
|
|
|
name,
|
|
|
|
"Name is set on named class via staging method when implementing " +
|
|
|
|
"and extending"
|
|
|
|
);
|
2011-03-05 00:33:47 -05:00
|
|
|
} )();
|
|
|
|
|
2011-03-05 13:13:53 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The class name should be provided in the error thrown when attempting to
|
|
|
|
* instantiate an abstract class, if it's available
|
|
|
|
*/
|
|
|
|
( function testClassNameIsGivenWhenTryingToInstantiateAbstractClass()
|
|
|
|
{
|
|
|
|
var name = 'Foo';
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
Class( name, { 'abstract foo': [] } )();
|
|
|
|
|
|
|
|
// we're not here to test to make sure it is thrown, but if it's not,
|
|
|
|
// then there's likely a problem
|
|
|
|
assert.fail(
|
|
|
|
"Was expecting instantiation error. There's a bug somewhere!"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
catch ( e )
|
|
|
|
{
|
|
|
|
assert.notEqual(
|
2011-03-06 10:37:20 -05:00
|
|
|
e.message.match( name ),
|
2011-03-05 13:13:53 -05:00
|
|
|
null,
|
|
|
|
"Abstract class instantiation error should contain class name"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// if no name is provided, then (anonymous) should be indicated
|
|
|
|
try
|
|
|
|
{
|
|
|
|
Class( { 'abstract foo': [] } )();
|
|
|
|
|
|
|
|
// we're not here to test to make sure it is thrown, but if it's not,
|
|
|
|
// then there's likely a problem
|
|
|
|
assert.fail(
|
|
|
|
"Was expecting instantiation error. There's a bug somewhere!"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
catch ( e )
|
|
|
|
{
|
|
|
|
assert.notEqual(
|
2011-03-06 10:37:20 -05:00
|
|
|
e.message.match( '(anonymous)' ),
|
2011-03-05 13:13:53 -05:00
|
|
|
null,
|
|
|
|
"Abstract class instantiation error should recognize that class " +
|
|
|
|
"is anonymous if no name was given"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
} )();
|
|
|
|
|