1
0
Fork 0

[#25] Began refactoring test-class_builder-static into new test case system

closure/master
Mike Gerwitz 2011-11-02 23:23:13 -04:00
parent 79d0c4a62c
commit 3912f2d369
2 changed files with 923 additions and 906 deletions

View File

@ -246,7 +246,10 @@ exports.prototype.validateGetterSetter = function(
) )
{ {
var prev = ( prev_data ) ? prev_data.member : null, var prev = ( prev_data ) ? prev_data.member : null,
prev_gs = ( ( prev_data.get || prev_data.set ) ? true : false ) prev_gs = ( ( prev_data && (prev_data.get || prev_data.set ) )
? true
: false
)
; ;
if ( prev || prev_gs ) if ( prev || prev_gs )

View File

@ -23,7 +23,6 @@
*/ */
var common = require( './common' ), var common = require( './common' ),
assert = require( 'assert' ),
fallback = common.require( 'util' ).definePropertyFallback() fallback = common.require( 'util' ).definePropertyFallback()
// XXX: get rid of this disgusting mess; we're mid-refactor and all these // XXX: get rid of this disgusting mess; we're mid-refactor and all these
@ -42,12 +41,14 @@ var common = require( './common' ),
; ;
/** require( 'common' ).testCase(
* To provide access to static members, this.__self is made available inside of
* instances.
*/
( function testSelfPropertyReferencesClassDefinition()
{ {
/**
* To provide access to static members, this.__self is made available inside
* of instances.
*/
'Self property references class definition': function()
{
var val = [ 'baz' ], var val = [ 'baz' ],
Foo = builder.build( Foo = builder.build(
{ {
@ -59,38 +60,38 @@ var common = require( './common' ),
Foo.bar = val; Foo.bar = val;
// we must use instanceof here because the __self object has the class in // we must use instanceof here because the __self object has the class
// its prototype chain // in its prototype chain
assert.ok( ( Foo().test().bar === Foo.bar ), this.assertOk( ( Foo().test().bar === Foo.bar ),
"__self property references class definition" "__self property references class definition"
); );
} )(); },
/** /**
* If a static property does not exist, the getter should return undefined. * If a static property does not exist, the getter should return undefined.
* *
* This test exists to ensure an error is not thrown if the property is not * This test exists to ensure an error is not thrown if the property is not
* found. This is because we check each parent and eventually reach the base * found. This is because we check each parent and eventually reach the base
* object. We must ensure the base object does not cause any problems. * object. We must ensure the base object does not cause any problems.
*/ */
( function testStaticPropertyLookupReturnsUndefinedIfNotFound() 'Static property lookup returns undefined if not found': function()
{ {
var result = builder.build( {} ).$( 'foo' ); var result = builder.build( {} ).$( 'foo' );
assert.equal( result, undefined, this.assertEqual( result, undefined,
"Static property getter should return undefined if not found" "Static property getter should return undefined if not found"
); );
} )(); },
/** /**
* If supported by the environment, ensure that the accessor method used to * If supported by the environment, ensure that the accessor method used to
* access static properties is not enumerable. It's unnecessary clutter (and * access static properties is not enumerable. It's unnecessary clutter (and
* confusion) otherwise. * confusion) otherwise.
*/ */
( function testStaticPropertyAccessorIsNotEnumerable() 'Static property accessor is not enumerable': function()
{ {
var get = Object.getOwnPropertyDescriptor, var get = Object.getOwnPropertyDescriptor,
Foo = builder.build( {} ); Foo = builder.build( {} );
@ -100,20 +101,20 @@ var common = require( './common' ),
return; return;
} }
assert.equal( get( Foo, '$' ).enumerable, false, this.assertEqual( get( Foo, '$' ).enumerable, false,
"Static property accessor method should not be enumerable" "Static property accessor method should not be enumerable"
); );
} )(); },
/** /**
* Static members, by their nature, should be accessible through the class * Static members, by their nature, should be accessible through the class
* definition itself; that is, without instantiation. It should also not be * definition itself; that is, without instantiation. It should also not be
* available through the generated prototype (and therefore, be unavailable to * available through the generated prototype (and therefore, be unavailable
* instances). * to instances).
*/ */
( function testPublicStaticMembersAreAccessibleViaClassDefinitionOnly() 'Public static members are accessible via class definition only': function()
{ {
var val = 'foo', var val = 'foo',
val2 = 'bar', val2 = 'bar',
Foo = builder.build( Foo = builder.build(
@ -136,39 +137,39 @@ var common = require( './common' ),
} ); } );
// properties should be accessible via class definition // properties should be accessible via class definition
assert.equal( Foo.$('foo'), val, this.assertEqual( Foo.$('foo'), val,
"Public static properties should be accessible via class definition" "Public static properties should be accessible via class definition"
); );
// as long as the above test succeeded, we can then conclude that static // as long as the above test succeeded, we can then conclude that static
// members are public by default if the following succeeds // members are public by default if the following succeeds
assert.equal( Foo.$('bar'), val2, this.assertEqual( Foo.$('bar'), val2,
"Static properties are public by default" "Static properties are public by default"
); );
// methods should be accessible via class definition // methods should be accessible via class definition
assert.equal( Foo.baz(), val, this.assertEqual( Foo.baz(), val,
"Public static methods should be accessible via class definition" "Public static methods should be accessible via class definition"
); );
// same rules as above, but with a method // same rules as above, but with a method
assert.equal( Foo.foobar(), val2, this.assertEqual( Foo.foobar(), val2,
"Static methods are public by default" "Static methods are public by default"
); );
// getter/setter method should not be a part of the prototype // getter/setter method should not be a part of the prototype
assert.equal( Foo.prototype.$, undefined, this.assertEqual( Foo.prototype.$, undefined,
"Public static properties are *not* part of the prototype" "Public static properties are *not* part of the prototype"
); );
} )(); },
/** /**
* Same as above, but with getters/setters. We can only run this test if * Same as above, but with getters/setters. We can only run this test if
* getters/setters are supported by the engine running it. * getters/setters are supported by the engine running it.
*/ */
( function testPublicStaticGettersSettersAreAccessibleViaClassDefinitionOnly() 'Public static getters/setter accessible via class dfn only': function()
{ {
// if unsupported, don't bother with the test // if unsupported, don't bother with the test
if ( fallback ) if ( fallback )
{ {
@ -199,45 +200,45 @@ var common = require( './common' ),
// define the class // define the class
var Foo = builder.build( def ); var Foo = builder.build( def );
assert.equal( Foo.foo, val, this.assertEqual( Foo.foo, val,
"Public static getters are accessible via class definition" "Public static getters are accessible via class definition"
); );
Foo.foo = 'moo'; Foo.foo = 'moo';
assert.equal( called[ 0 ], true, this.assertEqual( called[ 0 ], true,
"Public static setters are accessible via class definition" "Public static setters are accessible via class definition"
); );
assert.equal( Foo.bar, val, this.assertEqual( Foo.bar, val,
"Static getters are public by default" "Static getters are public by default"
); );
Foo.bar = 'moo'; Foo.bar = 'moo';
assert.equal( called[ 1 ], true, this.assertEqual( called[ 1 ], true,
"Static setters are public by default" "Static setters are public by default"
); );
// none of these should be available on the prototype // none of these should be available on the prototype
assert.equal( Foo.prototype.foo, undefined, this.assertEqual( Foo.prototype.foo, undefined,
"Public static getters/getters are unavailable on prototype (0)" "Public static getters/getters are unavailable on prototype (0)"
); );
assert.equal( Foo.prototype.bar, undefined, this.assertEqual( Foo.prototype.bar, undefined,
"Public static getters/getters are unavailable on prototype (1)" "Public static getters/getters are unavailable on prototype (1)"
); );
} )(); },
/** /**
* With non-static methods, 'this' is bound to the instance. In the case of * With non-static methods, 'this' is bound to the instance. In the case of
* static members, we should bind to the class definition (equivalent of * static members, we should bind to the class definition (equivalent of
* this.__self). * this.__self).
* *
* This functionality had already existed previously. When a propobj is not * This functionality had already existed previously. When a propobj is not
* available for an instance, it falls back. This serves as a regression test to * available for an instance, it falls back. This serves as a regression
* ensure this functionality remains. * test to ensure this functionality remains.
*/ */
( function testStaticMethodsNotBoundToInstance() 'Static methods not bound to instance': function()
{ {
var result = null, var result = null,
Foo = builder.build( Foo = builder.build(
{ {
@ -252,19 +253,19 @@ var common = require( './common' ),
// note that the objects themselves aren't the same, due to the property // note that the objects themselves aren't the same, due to the property
// object // object
assert.equal( result.foo, Foo.foo, this.assertEqual( result.foo, Foo.foo,
"Static members are bound to class definition rather than instance" "Static members are bound to class definition rather than instance"
); );
} )(); },
/** /**
* We don't have the benefit of static members being part of the prototype * We don't have the benefit of static members being part of the prototype
* chain. Inheritance is not automatic. This test deals only with ensuring that * chain. Inheritance is not automatic. This test deals only with ensuring
* *public* static members are inherited by subtypes. * that *public* static members are inherited by subtypes.
*/ */
( function testPublicStaticMembersAreInheritedBySubtypes() 'Public static members are inherited by subtypes': function()
{ {
var def = { var def = {
'public static foo': 'val', 'public static foo': 'val',
'public static func': function() {}, 'public static func': function() {},
@ -289,31 +290,32 @@ var common = require( './common' ),
// extends from the parent and adds an additional // extends from the parent and adds an additional
SubFoo = builder.build( Foo, { 'public static baz': baz } ), SubFoo = builder.build( Foo, { 'public static baz': baz } ),
// simply extends from the parent (also serves as a check to ensure that // simply extends from the parent (also serves as a check to ensure
// static members of *all* parents are inherited, not just the // that static members of *all* parents are inherited, not just the
// immediate) // immediate)
SubSubFoo = builder.build( SubFoo, {} ) SubSubFoo = builder.build( SubFoo, {} )
; ;
// properties // properties
assert.equal( SubFoo.$('foo'), Foo.$('foo'), this.assertEqual( SubFoo.$('foo'), Foo.$('foo'),
"Public static properties are inherited by subtypes" "Public static properties are inherited by subtypes"
); );
assert.equal( SubSubFoo.$('foo'), Foo.$('foo'), this.assertEqual( SubSubFoo.$('foo'), Foo.$('foo'),
"Public static properties are inherited by sub-subtypes" "Public static properties are inherited by sub-subtypes"
); );
// methods // methods
assert.deepEqual( SubFoo.func, Foo.func, this.assertDeepEqual( SubFoo.func, Foo.func,
"Public static methods are inherited by subtypes" "Public static methods are inherited by subtypes"
); );
assert.deepEqual( SubSubFoo.func, Foo.func, this.assertDeepEqual( SubSubFoo.func, Foo.func,
"Public static methods are inherited by sub-subtypes" "Public static methods are inherited by sub-subtypes"
); );
// merge // merge
assert.equal( SubFoo.$('baz'), baz, this.assertEqual( SubFoo.$('baz'), baz,
"Subtypes contain both inherited static members as well as their own" "Subtypes contain both inherited static members as well as their " +
"own"
); );
// getters/setters (if supported by engine) // getters/setters (if supported by engine)
@ -321,35 +323,38 @@ var common = require( './common' ),
{ {
var super_data = Object.getOwnPropertyDescriptor( Foo, 'bar' ), var super_data = Object.getOwnPropertyDescriptor( Foo, 'bar' ),
sub_data = Object.getOwnPropertyDescriptor( SubFoo, 'bar' ), sub_data = Object.getOwnPropertyDescriptor( SubFoo, 'bar' ),
sub_sub_data = Object.getOwnPropertyDescriptor( SubSubFoo, 'bar' ) sub_sub_data = Object.getOwnPropertyDescriptor(
SubSubFoo, 'bar'
)
; ;
// getters // getters
assert.deepEqual( super_data.get, sub_data.get, this.assertDeepEqual( super_data.get, sub_data.get,
"Public static getters are inherited by subtypes" "Public static getters are inherited by subtypes"
); );
assert.deepEqual( super_data.get, sub_sub_data.get, this.assertDeepEqual( super_data.get, sub_sub_data.get,
"Public static getters are inherited by sub-subtypes" "Public static getters are inherited by sub-subtypes"
); );
// setters // setters
assert.deepEqual( super_data.set, sub_data.set, this.assertDeepEqual( super_data.set, sub_data.set,
"Public static setters are inherited by subtypes" "Public static setters are inherited by subtypes"
); );
assert.deepEqual( super_data.set, sub_sub_data.set, this.assertDeepEqual( super_data.set, sub_sub_data.set,
"Public static setters are inherited by sub-subtypes" "Public static setters are inherited by sub-subtypes"
); );
} }
} )(); },
/** /**
* Static references should be inherited by subtypes. That is, modifying a * Static references should be inherited by subtypes. That is, modifying a
* static property of a supertype should modify the same static property of the * static property of a supertype should modify the same static property of
* subtype, so long as the subtype has not defined a property of the same name. * the subtype, so long as the subtype has not defined a property of the
* same name.
*/ */
( function testPublicStaticPropertyReferencesAreInheritedBySubtypes() 'Public static property references are inherited by subtypes': function()
{ {
var val = [ 1, 2, 3 ], var val = [ 1, 2, 3 ],
val2 = [ 'a', 'b', 'c' ], val2 = [ 'a', 'b', 'c' ],
@ -361,42 +366,42 @@ var common = require( './common' ),
; ;
// the properties should reference the same object // the properties should reference the same object
assert.ok( SubFoo.$('bar') === Foo.$('bar'), this.assertOk( SubFoo.$('bar') === Foo.$('bar'),
"Inherited static properties should share references" "Inherited static properties should share references"
); );
// setting a property on Foo should set the property on SubFoo and // setting a property on Foo should set the property on SubFoo and
// vice-versa // vice-versa
Foo.$( 'bar', val2 ); Foo.$( 'bar', val2 );
assert.deepEqual( Foo.$( 'bar' ), val2, this.assertDeepEqual( Foo.$( 'bar' ), val2,
"Can set static property values" "Can set static property values"
); );
assert.ok( Foo.$( 'bar' ) === SubFoo.$( 'bar' ), this.assertOk( Foo.$( 'bar' ) === SubFoo.$( 'bar' ),
"Setting a static property value on a supertype also sets the value " + "Setting a static property value on a supertype also sets the " +
"on subtypes" "value on subtypes"
); );
SubFoo.$( 'bar', val ); SubFoo.$( 'bar', val );
assert.ok( Foo.$( 'bar' ) === SubFoo.$( 'bar' ) ); this.assertOk( Foo.$( 'bar' ) === SubFoo.$( 'bar' ) );
} )(); },
/** /**
* Static members do not have the benefit of prototype chains. We must * Static members do not have the benefit of prototype chains. We must
* implement our own means of traversing the inheritance tree. This is done by * implement our own means of traversing the inheritance tree. This is done
* checking to see if a class has defined the requested property, then * by checking to see if a class has defined the requested property, then
* forwarding the call to the parent if it has not. * forwarding the call to the parent if it has not.
* *
* The process of looking up the property is very important. hasOwnProperty is * The process of looking up the property is very important. hasOwnProperty
* used rather than checking for undefined, because they have drastically * is used rather than checking for undefined, because they have drastically
* different results. Setting a value to undefined (if hasOwnProperty were not * different results. Setting a value to undefined (if hasOwnProperty were
* used) would effectively forward all requests to the base class (since no * not used) would effectively forward all requests to the base class (since
* property would be found), thereby preventing it from ever being written to * no property would be found), thereby preventing it from ever being
* again. * written to again.
*/ */
( function testSettingsStaticPropertiesToUndefinedWillNotCorruptLookupProcess() 'Setting static props to undefined will not corrupt lookup': function()
{ {
var val = 'baz', var val = 'baz',
Foo = builder.build( Foo = builder.build(
{ {
@ -406,31 +411,32 @@ var common = require( './common' ),
// first check to ensure we can set the value to null // first check to ensure we can set the value to null
Foo.$( 'foo', null ); Foo.$( 'foo', null );
assert.strictEqual( Foo.$( 'foo' ), null, this.assertStrictEqual( Foo.$( 'foo' ), null,
"Static properties may be set to null" "Static properties may be set to null"
); );
// then undefined (this actually won't do anything) // then undefined (this actually won't do anything)
Foo.$( 'foo', undefined ); Foo.$( 'foo', undefined );
assert.strictEqual( Foo.$( 'foo' ), undefined, this.assertStrictEqual( Foo.$( 'foo' ), undefined,
"Static properties may be set to undefined" "Static properties may be set to undefined"
); );
// then set back to a scalar // then set back to a scalar
Foo.$( 'foo', val ); Foo.$( 'foo', val );
assert.equal( Foo.$( 'foo' ), val, this.assertEqual( Foo.$( 'foo' ), val,
"Setting static property to undefined does not corrupt lookup process" "Setting static property to undefined does not corrupt lookup " +
"process"
); );
} )(); },
/** /**
* Ensure that the proper context is returned by static property setters. It * Ensure that the proper context is returned by static property setters. It
* should return the calling class, regardless of whether or not it owns the * should return the calling class, regardless of whether or not it owns the
* property being requested. * property being requested.
*/ */
( function testStaticPropertySettersReturnProperContext() 'Static property setters return proper context': function()
{ {
var Foo = builder.build( var Foo = builder.build(
{ {
'public static foo': '', 'public static foo': '',
@ -439,24 +445,24 @@ var common = require( './common' ),
SubFoo = builder.build( Foo, {} ) SubFoo = builder.build( Foo, {} )
; ;
assert.ok( Foo.$( 'foo', 'val' ) === Foo, this.assertOk( Foo.$( 'foo', 'val' ) === Foo,
"Static property setter returns self" "Static property setter returns self"
); );
assert.ok( SubFoo.$( 'foo', 'val' ) === SubFoo, this.assertOk( SubFoo.$( 'foo', 'val' ) === SubFoo,
"Static property setter returns calling class, even if property is " + "Static property setter returns calling class, even if property " +
"owned by a supertype" "is owned by a supertype"
); );
} )(); },
/** /**
* Users should not be permitted to set values of static properties that have * Users should not be permitted to set values of static properties that
* not been declared. * have not been declared.
*/ */
( function testAttemptingToSetUndeclaredStaticPropertyResultsInException() 'Attempting to set undeclared static prop results in exception': function()
{ {
assert.throws( this.assertThrows(
function() function()
{ {
// should throw an exception since property 'foo' has not been // should throw an exception since property 'foo' has not been
@ -467,15 +473,15 @@ var common = require( './common' ),
"Attempting to set an undeclaraed static property results in an " + "Attempting to set an undeclaraed static property results in an " +
"exception" "exception"
); );
} )(); },
/** /**
* Protected members should be available from within the class but shouldn't be * Protected members should be available from within the class but shouldn't
* exposed to the world * be exposed to the world
*/ */
( function testProtectedStaticMembersAreAvailableInsideClassOnly() 'Protected static members are available inside class only': function()
{ {
var val = 'foo', var val = 'foo',
Foo = builder.build( Foo = builder.build(
{ {
@ -511,34 +517,34 @@ var common = require( './common' ),
}, },
} ); } );
assert.equal( Foo.baz, undefined, this.assertEqual( Foo.baz, undefined,
"Protected methods should not be accessible outside the class" "Protected methods should not be accessible outside the class"
); );
assert.equal( Foo.staticBaz(), val, this.assertEqual( Foo.staticBaz(), val,
"Protected methods are accessible to static methods" "Protected methods are accessible to static methods"
); );
assert.equal( Foo().instBaz(), val, this.assertEqual( Foo().instBaz(), val,
"Protected methods are accessible to instance methods" "Protected methods are accessible to instance methods"
); );
assert.equal( Foo.staticGetProp(), val, this.assertEqual( Foo.staticGetProp(), val,
"Protected static properties are accessible to static methods" "Protected static properties are accessible to static methods"
); );
assert.equal( Foo().instGetProp(), val, this.assertEqual( Foo().instGetProp(), val,
"Protected static properties are accessible to instance methods" "Protected static properties are accessible to instance methods"
); );
} )(); },
/** /**
* Same as above, but with getters/setters. We can only run this test if * Same as above, but with getters/setters. We can only run this test if
* getters/setters are supported by the engine running it. * getters/setters are supported by the engine running it.
*/ */
( function testProtectedStaticGettersSettersAreAccessibleInsideClassesOnly() 'Protected static getters/setters accessible inside class only': function()
{ {
// if unsupported, don't bother with the test // if unsupported, don't bother with the test
if ( fallback ) if ( fallback )
{ {
@ -550,7 +556,8 @@ var common = require( './common' ),
var def = { var def = {
'public static getProp': function() 'public static getProp': function()
{ {
// getters/setters are not accessed using the accessor method // getters/setters are not accessed using the accessor
// method
return this.foo; return this.foo;
}, },
@ -572,29 +579,29 @@ var common = require( './common' ),
// define the class // define the class
var Foo = builder.build( def ); var Foo = builder.build( def );
assert.equal( Foo.getProp(), val, this.assertEqual( Foo.getProp(), val,
"Protected static getters are accessible from within the class" "Protected static getters are accessible from within the class"
); );
Foo.setProp( 'bla' ); Foo.setProp( 'bla' );
assert.equal( called[ 0 ], true, this.assertEqual( called[ 0 ], true,
"Protected static setters are accessible from within the class" "Protected static setters are accessible from within the class"
); );
assert.equal( Foo.foo, undefined, this.assertEqual( Foo.foo, undefined,
"Protected static getters/getters are not public" "Protected static getters/getters are not public"
); );
} )(); },
/** /**
* As usual, protected members (in this case, static) should be inherited by * As usual, protected members (in this case, static) should be inherited by
* subtypes. * subtypes.
* *
* Long function is long. Kids, don't do this at home. * Long function is long. Kids, don't do this at home.
*/ */
( function testProtectedStaticMembersAreInheritedBySubtypes() 'Protected static members are inherited by subtypes': function()
{ {
var val = 'baz', var val = 'baz',
val2 = 'bazbaz', val2 = 'bazbaz',
def = { def = {
@ -651,24 +658,26 @@ var common = require( './common' ),
SubSubFoo = builder.build( SubFoo, {} ) SubSubFoo = builder.build( SubFoo, {} )
; ;
assert.equal( SubFoo.bar(), val, this.assertEqual( SubFoo.bar(), val,
"Subtypes inherit parents' protected static methods" "Subtypes inherit parents' protected static methods"
); );
assert.equal( SubFoo.bar2(), val2, this.assertEqual( SubFoo.bar2(), val2,
"Static methods have access to other static methods in the same class" "Static methods have access to other static methods in the same " +
"class"
); );
// for extra assurance, to ensure our recursive implementation is correct // for extra assurance, to ensure our recursive implementation is
assert.equal( SubSubFoo.bar(), val, // correct
this.assertEqual( SubSubFoo.bar(), val,
"Sub-subtypes inherit parents' protected static methods" "Sub-subtypes inherit parents' protected static methods"
); );
assert.equal( SubFoo.getProp(), val, this.assertEqual( SubFoo.getProp(), val,
"Subtypes inherit parents' protected static properties" "Subtypes inherit parents' protected static properties"
); );
assert.equal( SubSubFoo.getProp(), val, this.assertEqual( SubSubFoo.getProp(), val,
"Sub-subtypes inherit parents' protected static properties" "Sub-subtypes inherit parents' protected static properties"
); );
@ -681,30 +690,30 @@ var common = require( './common' ),
; ;
// getters // getters
assert.deepEqual( super_data.get, sub_data.get, this.assertDeepEqual( super_data.get, sub_data.get,
"Protected static getters are inherited by subtypes" "Protected static getters are inherited by subtypes"
); );
assert.deepEqual( super_data.get, sub_sub_data.get, this.assertDeepEqual( super_data.get, sub_sub_data.get,
"Protected static getters are inherited by sub-subtypes" "Protected static getters are inherited by sub-subtypes"
); );
// setters // setters
assert.deepEqual( super_data.set, sub_data.set, this.assertDeepEqual( super_data.set, sub_data.set,
"Protected static setters are inherited by subtypes" "Protected static setters are inherited by subtypes"
); );
assert.deepEqual( super_data.set, sub_sub_data.set, this.assertDeepEqual( super_data.set, sub_sub_data.set,
"Protected static setters are inherited by sub-subtypes" "Protected static setters are inherited by sub-subtypes"
); );
} }
} )(); },
/** /**
* Private members should be available from within the class, but not outside of * Private members should be available from within the class, but not
* it * outside of it
*/ */
( function testPrivateStaticMembersAreAvailableInsideClassOnly() 'Private static members are available inside class only': function()
{ {
var val = 'foo', var val = 'foo',
Foo = builder.build( Foo = builder.build(
{ {
@ -740,34 +749,34 @@ var common = require( './common' ),
}, },
} ); } );
assert.equal( Foo.baz, undefined, this.assertEqual( Foo.baz, undefined,
"Private methods should not be accessible outside the class" "Private methods should not be accessible outside the class"
); );
assert.equal( Foo.staticBaz(), val, this.assertEqual( Foo.staticBaz(), val,
"Private methods are accessible to static methods" "Private methods are accessible to static methods"
); );
assert.equal( Foo().instBaz(), val, this.assertEqual( Foo().instBaz(), val,
"Private methods are accessible to instance methods" "Private methods are accessible to instance methods"
); );
assert.equal( Foo.staticGetProp(), val, this.assertEqual( Foo.staticGetProp(), val,
"Private static properties are accessible to static methods" "Private static properties are accessible to static methods"
); );
assert.equal( Foo().instGetProp(), val, this.assertEqual( Foo().instGetProp(), val,
"Private static properties are accessible to instance methods" "Private static properties are accessible to instance methods"
); );
} )(); },
/** /**
* Private static members should not be inherited by subtypes. Of course. Moving * Private static members should not be inherited by subtypes. Of course.
* along... * Moving along...
*/ */
( function testPrivateStaticMembersAreNotInheritedBySubtypes() 'Private static members are not inherited by subtypes': function()
{ {
var def = { var def = {
'private static prop': 'foo', 'private static prop': 'foo',
'private static priv': function() {}, 'private static priv': function() {},
@ -810,30 +819,32 @@ var common = require( './common' ),
} ) } )
; ;
assert.equal( SubFoo.getPriv(), undefined, this.assertEqual( SubFoo.getPriv(), undefined,
"Private static methods should not be inherited by subtypes" "Private static methods should not be inherited by subtypes"
); );
assert.equal( SubFoo.getGetSet(), undefined, this.assertEqual( SubFoo.getGetSet(), undefined,
"Private static getters/setters should not be inherited by subtypes" "Private static getters/setters should not be inherited by subtypes"
); );
assert.equal( SubFoo().instGetProp(), undefined, this.assertEqual( SubFoo().instGetProp(), undefined,
"Private static properties should not be inherited by subtypes (inst)" "Private static properties should not be inherited by subtypes " +
"(inst)"
); );
assert.equal( SubFoo.staticGetProp(), undefined, this.assertEqual( SubFoo.staticGetProp(), undefined,
"Private static properties should not be inherited by subtypes (static)" "Private static properties should not be inherited by subtypes " +
"(static)"
); );
} )(); },
/** /**
* Same as above, but with getters/setters. We can only run this test if * Same as above, but with getters/setters. We can only run this test if
* getters/setters are supported by the engine running it. * getters/setters are supported by the engine running it.
*/ */
( function testPrivateStaticGettersSettersAreAccessibleInsideClassesOnly() 'Private static getters/setters accessible inside class only': function()
{ {
// if unsupported, don't bother with the test // if unsupported, don't bother with the test
if ( fallback ) if ( fallback )
{ {
@ -845,7 +856,8 @@ var common = require( './common' ),
var def = { var def = {
'public static getProp': function() 'public static getProp': function()
{ {
// getters/setters are not accessed using the accessor method // getters/setters are not accessed using the accessor
// method
return this.foo; return this.foo;
}, },
@ -867,27 +879,27 @@ var common = require( './common' ),
// define the class // define the class
var Foo = builder.build( def ); var Foo = builder.build( def );
assert.equal( Foo.getProp(), val, this.assertEqual( Foo.getProp(), val,
"Private static getters are accessible from within the class" "Private static getters are accessible from within the class"
); );
Foo.setProp( 'bla' ); Foo.setProp( 'bla' );
assert.equal( called[ 0 ], true, this.assertEqual( called[ 0 ], true,
"Private static setters are accessible from within the class" "Private static setters are accessible from within the class"
); );
assert.equal( Foo.foo, undefined, this.assertEqual( Foo.foo, undefined,
"Private static getters/getters are not public" "Private static getters/getters are not public"
); );
} )(); },
/** /**
* Public and protected static methods should be able to be overridden by * Public and protected static methods should be able to be overridden by
* subtypes. We needn't test private methods, as they are not inherited. * subtypes. We needn't test private methods, as they are not inherited.
*/ */
( function testStaticMethodsCanBeOverriddenBySubtypes() 'Static methods can be overridden by subtypes': function()
{ {
var val = 'bar', var val = 'bar',
Foo = builder.build( Foo = builder.build(
{ {
@ -913,25 +925,26 @@ var common = require( './common' ),
}, },
} ); } );
assert.equal( SubFoo.foo(), val, this.assertEqual( SubFoo.foo(), val,
"Public static methods can be overridden by subtypes" "Public static methods can be overridden by subtypes"
); );
assert.equal( SubFoo.prot(), val, this.assertEqual( SubFoo.prot(), val,
"Protected static methods can be overridden by subtypes" "Protected static methods can be overridden by subtypes"
); );
} )(); },
/** /**
* This tests very closely to the implementation, which is not good. However, * This tests very closely to the implementation, which is not good.
* it's important to protecting the data. The accessor method works off of * However, it's important to protecting the data. The accessor method works
* context, so it's important to ensure that the data will remain encapsulated * off of context, so it's important to ensure that the data will remain
* if the user attempts to be tricky and bind to a supertype. * encapsulated if the user attempts to be tricky and bind to a supertype.
*/ */
( function testCannotExploitAccessorMethodToGainAccessToParentPrivateProps() 'Cannot exploit accessor method to gain access to parent private props':
{ function()
{
var Foo = builder.build( var Foo = builder.build(
{ {
'private static foo': 'bar', 'private static foo': 'bar',
@ -946,18 +959,18 @@ var common = require( './common' ),
} ) } )
; ;
assert.equal( SubFoo.getParentPrivate(), undefined, this.assertEqual( SubFoo.getParentPrivate(), undefined,
"Cannot exploit accses modifier to gain access to parent private props" "Cannot exploit accses modifier to gain access to parent private props"
); );
} )(); },
/** /**
* Static members cannot be overridden. Instead, static members can be *hidden* * Static members cannot be overridden. Instead, static members can be
* if a member of the same name is defined by a subtype. * *hidden* if a member of the same name is defined by a subtype.
*/ */
( function testCannotOverrideStaticMembers() 'Cannot override static members': function()
{ {
var val_orig = 'foobaz', var val_orig = 'foobaz',
val = 'foobar', val = 'foobar',
@ -1000,29 +1013,29 @@ var common = require( './common' ),
; ;
// cannot override // cannot override
assert.notEqual( SubFoo.foo(), val, this.assertNotEqual( SubFoo.foo(), val,
"System does not support overriding static methods" "System does not support overriding static methods"
); );
assert.notEqual( SubFoo.baz(), val, this.assertNotEqual( SubFoo.baz(), val,
"System does not support overriding static properties" "System does not support overriding static properties"
); );
// but we can hide them // but we can hide them
assert.equal( SubFoo.bar(), val, this.assertEqual( SubFoo.bar(), val,
"System supports static method hiding" "System supports static method hiding"
); );
assert.equal( SubFoo.getProp(), val, this.assertEqual( SubFoo.getProp(), val,
"System supports static property hiding" "System supports static property hiding"
); );
} )(); },
/** /**
* Since members are statically bound, calls to parent methods should retain * Since members are statically bound, calls to parent methods should retain
* access to their private members. * access to their private members.
*/ */
( function testCallsToParentStaticMethodsRetainPrivateMemberAccess() 'Calls to parent static methods retain private member access': function()
{ {
var val = 'foobar', var val = 'foobar',
Foo = builder.build( Foo = builder.build(
{ {
@ -1043,14 +1056,15 @@ var common = require( './common' ),
} ) } )
; ;
assert.equal( SubFoo.getPriv(), val, this.assertEqual( SubFoo.getPriv(), val,
'Calls to parent static methods should retain access to their own ' + 'Calls to parent static methods should retain access to their own ' +
'private members when called externally' 'private members when called externally'
); );
assert.equal( SubFoo.getPriv2(), val, this.assertEqual( SubFoo.getPriv2(), val,
'Calls to parent static methods should retain access to their own ' + 'Calls to parent static methods should retain access to their own ' +
'private members when called internally' 'private members when called internally'
); );
} )(); },
} );