1
0
Fork 0

Moved test-class-visibility into suite as Class/VisibilityTest

perfodd
Mike Gerwitz 2014-01-07 04:02:12 -05:00
parent 85a201558d
commit d8243707ad
1 changed files with 167 additions and 154 deletions

View File

@ -19,121 +19,126 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
var common = require( './common' ), var pub = 'foo',
Class = common.require( 'class' ),
Interface = common.require( 'interface' ),
util = common.require( 'util' ),
pub = 'foo',
prot = 'bar', prot = 'bar',
priv = 'baz', priv = 'baz',
pubf = function() { return pub; }, pubf = function() { return pub; },
protf = function() { return prot; }, protf = function() { return prot; },
privf = function() { return priv; }, privf = function() { return priv; }
// new anonymous class instance
Foo = Class.extend( {
'public pub': pub,
'protected peeps': prot,
'private parts': priv,
'public pubf': pubf,
'protected protf': protf,
'private privf': privf,
'virtual public getProp': function( name )
{
// return property, allowing us to break encapsulation for
// protected/private properties (for testing purposes)
return this[ name ];
},
/**
* Does the same as the above, but we won't override this one
*/
'public nonOverrideGetProp': function( name )
{
return this[ name ];
},
/**
* Allows us to set a value from within the class
*/
'public setValue': function( name, value )
{
this[ name ] = value;
},
'public getSelf': function()
{
return this;
},
'virtual public getSelfOverride': function()
{
// override me
},
'public getPrivProp': function()
{
return this.parts;
},
'public invokePriv': function()
{
return this._priv();
},
'private _priv': function()
{
return priv;
},
}),
// instance of Foo
foo = Foo(),
// subtype
SubFoo = Foo.extend({
'private _pfoo': 'baz',
'override public getSelfOverride': function()
{
// return this from overridden method
return this;
},
/**
* We have to override this so that 'this' is not bound to the supertype
*/
'override public getProp': function( name )
{
// return property, allowing us to break encapsulation for
// protected/private properties (for testing purposes)
return this[ name ];
},
'private myOwnPrivateFoo': function() {},
}),
sub_foo = SubFoo(),
sub_sub_foo = SubFoo.extend( {} )()
; ;
require( 'common' ).testCase( require( 'common' ).testCase(
{ {
caseSetUp: function()
{
this.Class = this.require( 'class' );
this.Interface = this.require( 'interface' );
this.util = this.require( 'util' );
// new anonymous class instance
this.Foo = this.Class.extend( {
'public pub': pub,
'protected peeps': prot,
'private parts': priv,
'public pubf': pubf,
'protected protf': protf,
'private privf': privf,
'virtual public getProp': function( name )
{
// return property, allowing us to break encapsulation for
// protected/private properties (for testing purposes)
return this[ name ];
},
/**
* Does the same as the above, but we won't override this one
*/
'public nonOverrideGetProp': function( name )
{
return this[ name ];
},
/**
* Allows us to set a value from within the class
*/
'public setValue': function( name, value )
{
this[ name ] = value;
},
'public getSelf': function()
{
return this;
},
'virtual public getSelfOverride': function()
{
// override me
},
'public getPrivProp': function()
{
return this.parts;
},
'public invokePriv': function()
{
return this._priv();
},
'private _priv': function()
{
return priv;
},
} );
// subtype
this.SubFoo = this.Foo.extend( {
'private _pfoo': 'baz',
'override public getSelfOverride': function()
{
// return this from overridden method
return this;
},
/**
* We have to override this so that 'this' is not bound to the supertype
*/
'override public getProp': function( name )
{
// return property, allowing us to break encapsulation for
// protected/private properties (for testing purposes)
return this[ name ];
},
'private myOwnPrivateFoo': function() {},
} );
},
setUp: function()
{
// instance of Foo
this.foo = this.Foo();
this.sub_foo = this.SubFoo();
},
/** /**
* Public members are the only members added to the instance's prototype to * Public members are the only members added to the instance's prototype to
* be accessible externally * be accessible externally
@ -141,13 +146,13 @@ require( 'common' ).testCase(
'Public members are accessible externally': function() 'Public members are accessible externally': function()
{ {
this.assertEqual( this.assertEqual(
foo.pub, this.foo.pub,
pub, pub,
"Public properties are accessible via public interface" "Public properties are accessible via public interface"
); );
this.assertEqual( this.assertEqual(
foo.pubf(), this.foo.pubf(),
pub, pub,
"Public methods are accessible via public interface" "Public methods are accessible via public interface"
); );
@ -166,13 +171,13 @@ require( 'common' ).testCase(
'Public members are accessible internally': function() 'Public members are accessible internally': function()
{ {
this.assertEqual( this.assertEqual(
foo.getProp( 'pub' ), this.foo.getProp( 'pub' ),
pub, pub,
"Public properties are accessible internally" "Public properties are accessible internally"
); );
this.assertEqual( this.assertEqual(
foo.getProp( 'pubf' )(), this.foo.getProp( 'pubf' )(),
pub, pub,
"Public methods are accessible internally" "Public methods are accessible internally"
); );
@ -197,11 +202,11 @@ require( 'common' ).testCase(
var val = 'moomookittypoo'; var val = 'moomookittypoo';
// start by setting the value // start by setting the value
foo.setValue( 'pub', val ); this.foo.setValue( 'pub', val );
// we should see that change internally... // we should see that change internally...
this.assertEqual( this.assertEqual(
foo.getProp( 'pub' ), this.foo.getProp( 'pub' ),
val, val,
"Setting the value of a public property internally should be " + "Setting the value of a public property internally should be " +
"observable /internally/" "observable /internally/"
@ -209,7 +214,7 @@ require( 'common' ).testCase(
// ...as well as externally // ...as well as externally
this.assertEqual( this.assertEqual(
foo.pub, this.foo.pub,
val, val,
"Setting the value of a public property internally should be " + "Setting the value of a public property internally should be " +
"observable /externally/" "observable /externally/"
@ -221,31 +226,31 @@ require( 'common' ).testCase(
{ {
// browsers that do not support the property proxy will not support // browsers that do not support the property proxy will not support
// encapsulating properties // encapsulating properties
if ( util.definePropertyFallback() ) if ( this.util.definePropertyFallback() )
{ {
return; return;
} }
this.assertEqual( this.assertEqual(
foo.peeps, this.foo.peeps,
undefined, undefined,
"Protected properties are inaccessible via public interface" "Protected properties are inaccessible via public interface"
); );
this.assertEqual( this.assertEqual(
foo.parts, this.foo.parts,
undefined, undefined,
"Private properties are inaccessible via public interface" "Private properties are inaccessible via public interface"
); );
this.assertEqual( this.assertEqual(
foo.protf, this.foo.protf,
undefined, undefined,
"Protected methods are inaccessible via public interface" "Protected methods are inaccessible via public interface"
); );
this.assertEqual( this.assertEqual(
foo.privf, this.foo.privf,
undefined, undefined,
"Private methods are inaccessible via public interface" "Private methods are inaccessible via public interface"
); );
@ -258,7 +263,7 @@ require( 'common' ).testCase(
'Protected members are accessible internally': function() 'Protected members are accessible internally': function()
{ {
this.assertEqual( this.assertEqual(
foo.getProp( 'peeps' ), this.foo.getProp( 'peeps' ),
prot, prot,
"Protected properties are available internally" "Protected properties are available internally"
); );
@ -266,7 +271,7 @@ require( 'common' ).testCase(
// invoke rather than checking for equality, because the method may be // invoke rather than checking for equality, because the method may be
// wrapped // wrapped
this.assertEqual( this.assertEqual(
foo.getProp( 'protf' )(), this.foo.getProp( 'protf' )(),
prot, prot,
"Protected methods are available internally" "Protected methods are available internally"
); );
@ -279,7 +284,7 @@ require( 'common' ).testCase(
'Private members are accessible internally': function() 'Private members are accessible internally': function()
{ {
this.assertEqual( this.assertEqual(
foo.getProp( 'parts' ), this.foo.getProp( 'parts' ),
priv, priv,
"Private properties are available internally" "Private properties are available internally"
); );
@ -287,7 +292,7 @@ require( 'common' ).testCase(
// invoke rather than checking for equality, because the method may be // invoke rather than checking for equality, because the method may be
// wrapped // wrapped
this.assertEqual( this.assertEqual(
foo.getProp( 'privf' )(), this.foo.getProp( 'privf' )(),
priv, priv,
"Private methods are available internally" "Private methods are available internally"
); );
@ -300,7 +305,7 @@ require( 'common' ).testCase(
'Protected members are inherited from parent': function() 'Protected members are inherited from parent': function()
{ {
this.assertEqual( this.assertEqual(
sub_foo.getProp( 'peeps' ), this.sub_foo.getProp( 'peeps' ),
prot, prot,
"Protected properties are available to subtypes" "Protected properties are available to subtypes"
); );
@ -308,7 +313,7 @@ require( 'common' ).testCase(
// invoke rather than checking for equality, because the method may be // invoke rather than checking for equality, because the method may be
// wrapped // wrapped
this.assertEqual( this.assertEqual(
sub_foo.getProp( 'protf' )(), this.sub_foo.getProp( 'protf' )(),
prot, prot,
"Protected methods are available to subtypes" "Protected methods are available to subtypes"
); );
@ -323,13 +328,13 @@ require( 'common' ).testCase(
{ {
// browsers that do not support the property proxy will not support // browsers that do not support the property proxy will not support
// encapsulating properties // encapsulating properties
if ( util.definePropertyFallback() ) if ( this.util.definePropertyFallback() )
{ {
return; return;
} }
this.assertEqual( this.assertEqual(
sub_foo.getProp( 'parts' ), this.sub_foo.getProp( 'parts' ),
undefined, undefined,
"Private properties of supertypes should be unavailable to subtypes" "Private properties of supertypes should be unavailable to subtypes"
); );
@ -337,7 +342,7 @@ require( 'common' ).testCase(
// invoke rather than checking for equality, because the method may be // invoke rather than checking for equality, because the method may be
// wrapped // wrapped
this.assertEqual( this.assertEqual(
sub_foo.getProp( 'privf' ), this.sub_foo.getProp( 'privf' ),
undefined, undefined,
"Private methods of supertypes should be unavailable to subtypes" "Private methods of supertypes should be unavailable to subtypes"
); );
@ -353,22 +358,22 @@ require( 'common' ).testCase(
{ {
var val = 'foobar'; var val = 'foobar';
foo.setValue( 'prot', val ); this.foo.setValue( 'prot', val );
// ensure that class instances do not share values (ensuring the same // ensure that class instances do not share values (ensuring the same
// object isn't somehow being passed around) // object isn't somehow being passed around)
this.assertNotEqual( this.assertNotEqual(
sub_foo.getProp( 'prot' ), this.sub_foo.getProp( 'prot' ),
val, val,
"Class instances do not share protected values (subtype)" "Class instances do not share protected values (subtype)"
); );
// do the same for multiple instances of the same type // do the same for multiple instances of the same type
var sub_foo2 = SubFoo(); var sub_foo2 = this.SubFoo();
sub_foo2.setValue( 'prot', val ); sub_foo2.setValue( 'prot', val );
this.assertNotEqual( this.assertNotEqual(
sub_foo.getProp( 'prot' ), this.sub_foo.getProp( 'prot' ),
val, val,
"Class instances do not share protected values (same type)" "Class instances do not share protected values (same type)"
); );
@ -389,22 +394,22 @@ require( 'common' ).testCase(
'Returning self from method should return instance not prop obj': function() 'Returning self from method should return instance not prop obj': function()
{ {
this.assertDeepEqual( this.assertDeepEqual(
foo.getSelf(), this.foo.getSelf(),
foo, this.foo,
"Returning 'this' from a method should return instance of self" "Returning 'this' from a method should return instance of self"
); );
// what happens in the case of inheritance? // what happens in the case of inheritance?
this.assertDeepEqual( this.assertDeepEqual(
sub_foo.getSelf(), this.sub_foo.getSelf(),
sub_foo, this.sub_foo,
"Returning 'this' from a super method should return the subtype" "Returning 'this' from a super method should return the subtype"
); );
// finally, overridden methods should still return the instance // finally, overridden methods should still return the instance
this.assertDeepEqual( this.assertDeepEqual(
sub_foo.getSelfOverride(), this.sub_foo.getSelfOverride(),
sub_foo, this.sub_foo,
"Returning 'this' from a overridden method should return subtype" "Returning 'this' from a overridden method should return subtype"
); );
}, },
@ -428,7 +433,7 @@ require( 'common' ).testCase(
{ {
// properties // properties
this.assertEqual( this.assertEqual(
sub_foo.getPrivProp(), this.sub_foo.getPrivProp(),
priv, priv,
"Parent methods should have access to the private properties of " + "Parent methods should have access to the private properties of " +
"the parent" "the parent"
@ -436,12 +441,14 @@ require( 'common' ).testCase(
// methods // methods
this.assertEqual( this.assertEqual(
sub_foo.invokePriv(), this.sub_foo.invokePriv(),
priv, priv,
"Parent methods should have access to the private methods of the " + "Parent methods should have access to the private methods of the " +
"parent" "parent"
); );
var sub_sub_foo = this.SubFoo.extend( {} )()
// should apply to super-supertypes too // should apply to super-supertypes too
this.assertEqual( this.assertEqual(
sub_sub_foo.getPrivProp(), sub_sub_foo.getPrivProp(),
@ -484,14 +491,14 @@ require( 'common' ).testCase(
{ {
// browsers that do not support the property proxy will not support // browsers that do not support the property proxy will not support
// encapsulating properties // encapsulating properties
if ( util.definePropertyFallback() ) if ( this.util.definePropertyFallback() )
{ {
return; return;
} }
// property // property
this.assertEqual( this.assertEqual(
sub_foo.nonOverrideGetProp( '_pfoo' ), this.sub_foo.nonOverrideGetProp( '_pfoo' ),
undefined, undefined,
"Parent should not have access to private properties of subtype " + "Parent should not have access to private properties of subtype " +
"whena parent method is invoked" "whena parent method is invoked"
@ -499,7 +506,7 @@ require( 'common' ).testCase(
// member // member
this.assertEqual( this.assertEqual(
sub_foo.nonOverrideGetProp( '_myOwnPrivateFoo' ), this.sub_foo.nonOverrideGetProp( '_myOwnPrivateFoo' ),
undefined, undefined,
"Parent should not have access to private methods of subtype " + "Parent should not have access to private methods of subtype " +
"when a parent method is invoked" "when a parent method is invoked"
@ -512,10 +519,12 @@ require( 'common' ).testCase(
*/ */
'Can escalate member visibility': function() 'Can escalate member visibility': function()
{ {
var _self = this;
// escalate // escalate
this.assertDoesNotThrow( function() this.assertDoesNotThrow( function()
{ {
Class( _self.Class(
{ {
'protected foo': 'bar', 'protected foo': 'bar',
'virtual protected baz': function() {}, 'virtual protected baz': function() {},
@ -528,7 +537,7 @@ require( 'common' ).testCase(
// same level of visibility // same level of visibility
this.assertDoesNotThrow( function() this.assertDoesNotThrow( function()
{ {
Class( _self.Class(
{ {
'protected foo': 'bar', 'protected foo': 'bar',
'virtual protected baz': function() {}, 'virtual protected baz': function() {},
@ -546,10 +555,12 @@ require( 'common' ).testCase(
*/ */
'Cannot de-escalate member visibility': function() 'Cannot de-escalate member visibility': function()
{ {
var _self = this;
// public -> protected // public -> protected
this.assertThrows( function() this.assertThrows( function()
{ {
Class( _self.Class(
{ {
'public foo': 'bar', 'public foo': 'bar',
} ).extend( { } ).extend( {
@ -559,7 +570,7 @@ require( 'common' ).testCase(
this.assertThrows( function() this.assertThrows( function()
{ {
Class( _self.Class(
{ {
'virtual public baz': function() {}, 'virtual public baz': function() {},
} ).extend( { } ).extend( {
@ -571,7 +582,7 @@ require( 'common' ).testCase(
// public -> private // public -> private
this.assertThrows( function() this.assertThrows( function()
{ {
Class( _self.Class(
{ {
'public foo': 'bar', 'public foo': 'bar',
} ).extend( { } ).extend( {
@ -581,7 +592,7 @@ require( 'common' ).testCase(
this.assertThrows( function() this.assertThrows( function()
{ {
Class( _self.Class(
{ {
'virtual public baz': function() {}, 'virtual public baz': function() {},
} ).extend( { } ).extend( {
@ -593,7 +604,7 @@ require( 'common' ).testCase(
// protected -> private // protected -> private
this.assertThrows( function() this.assertThrows( function()
{ {
Class( _self.Class(
{ {
'protected foo': 'bar', 'protected foo': 'bar',
} ).extend( { } ).extend( {
@ -603,7 +614,7 @@ require( 'common' ).testCase(
this.assertThrows( function() this.assertThrows( function()
{ {
Class( _self.Class(
{ {
'virtual protected baz': function() {}, 'virtual protected baz': function() {},
} ).extend( { } ).extend( {
@ -622,7 +633,7 @@ require( 'common' ).testCase(
'Calling super method works properly with protected methods': function() 'Calling super method works properly with protected methods': function()
{ {
var val = 'foobar', var val = 'foobar',
result = Class( { result = this.Class( {
'virtual protected foo': function() 'virtual protected foo': function()
{ {
return val; return val;
@ -650,9 +661,11 @@ require( 'common' ).testCase(
*/ */
'Visibility de-escalation rulse apply to interfaces': function() 'Visibility de-escalation rulse apply to interfaces': function()
{ {
var _self = this;
this.assertThrows( function() this.assertThrows( function()
{ {
Class.implement( Interface( { 'abstract public foo': [] } ) ) Class.implement( _self.Interface( { 'abstract public foo': [] } ) )
.extend( .extend(
{ {
// should throw an exception; visibility de-escalation // should throw an exception; visibility de-escalation
@ -675,7 +688,7 @@ require( 'common' ).testCase(
'Can override protected method functionality with public': function() 'Can override protected method functionality with public': function()
{ {
// get the result of invoking overridden foo() // get the result of invoking overridden foo()
var result = Class( var result = this.Class(
{ {
'virtual protected foo': function() 'virtual protected foo': function()
{ {
@ -708,7 +721,7 @@ require( 'common' ).testCase(
'Protected values are available to subtypes when set by parent': function() 'Protected values are available to subtypes when set by parent': function()
{ {
var expected = 5, var expected = 5,
result = Class( result = this.Class(
{ {
'protected val': 0, 'protected val': 0,
@ -742,7 +755,7 @@ require( 'common' ).testCase(
'Can properly override protected with protected': function() 'Can properly override protected with protected': function()
{ {
var val = 'foobar', var val = 'foobar',
result = Class( result = this.Class(
{ {
'virtual protected foo': function() {}, 'virtual protected foo': function() {},
} ).extend( } ).extend(