1
0
Fork 0
mirror of https://github.com/jashkenas/coffeescript.git synced 2022-11-09 12:23:24 -05:00

continuing with the ol' refactorTests

This commit is contained in:
Jeremy Ashkenas 2011-03-11 21:55:26 -05:00
parent 9e2c75b548
commit d30c125ab7
4 changed files with 347 additions and 324 deletions

View file

@ -4,27 +4,27 @@
# * Array Literals
# * Splats in Array Literals
# TODO: refactor array literal tests
# TODO: add indexing and method invocation tests: [1][0] is 1, [].toString()
trailingComma = [1, 2, 3,]
ok (trailingComma[0] is 1) and (trailingComma[2] is 3) and (trailingComma.length is 3)
test "trailing commas", ->
trailingComma = [1, 2, 3,]
ok (trailingComma[0] is 1) and (trailingComma[2] is 3) and (trailingComma.length is 3)
trailingComma = [
trailingComma = [
1, 2, 3,
4, 5, 6
7, 8, 9,
]
(sum = (sum or 0) + n) for n in trailingComma
]
(sum = (sum or 0) + n) for n in trailingComma
a = [((x) -> x), ((x) -> x * x)]
ok a.length is 2
a = [((x) -> x), ((x) -> x * x)]
ok a.length is 2
# Funky indentation within non-comma-seperated arrays.
result = [['a']
test "incorrect indentation without commas", ->
result = [['a']
{b: 'c'}]
ok result[0][0] is 'a'
ok result[1]['b'] is 'c'
ok result[0][0] is 'a'
ok result[1]['b'] is 'c'
# Splats in Array Literals

View file

@ -1,8 +1,6 @@
# Assignment
# ----------
# TODO: organize assignment file
# * Assignment
# * Compound Assignment
# * Destructuring Assignment

View file

@ -3,19 +3,19 @@
# TODO: add method invocation tests: true.toString() is "true"
#764: Boolean should be indexable
toString = Boolean::toString
test "#764 Booleans should be indexable", ->
toString = Boolean::toString
eq toString, true['toString']
eq toString, false['toString']
eq toString, yes['toString']
eq toString, no['toString']
eq toString, on['toString']
eq toString, off['toString']
eq toString, true['toString']
eq toString, false['toString']
eq toString, yes['toString']
eq toString, no['toString']
eq toString, on['toString']
eq toString, off['toString']
eq toString, true.toString
eq toString, false.toString
eq toString, yes.toString
eq toString, no.toString
eq toString, on.toString
eq toString, off.toString
eq toString, true.toString
eq toString, false.toString
eq toString, yes.toString
eq toString, no.toString
eq toString, on.toString
eq toString, off.toString

View file

@ -5,114 +5,120 @@
# * Class Instantiation
# * Inheritance and Super
# TODO: refactor class tests
test "classes with a four-level inheritance chain", ->
# Test classes with a four-level inheritance chain.
class Base
class Base
func: (string) ->
"zero/#{string}"
@static: (string) ->
"static/#{string}"
class FirstChild extends Base
class FirstChild extends Base
func: (string) ->
super('one/') + string
SecondChild = class extends FirstChild
SecondChild = class extends FirstChild
func: (string) ->
super('two/') + string
thirdCtor = ->
thirdCtor = ->
@array = [1, 2, 3]
class ThirdChild extends SecondChild
class ThirdChild extends SecondChild
constructor: -> thirdCtor.call this
# Gratuitous comment for testing.
func: (string) ->
super('three/') + string
result = (new ThirdChild).func 'four'
result = (new ThirdChild).func 'four'
ok result is 'zero/one/two/three/four'
ok Base.static('word') is 'static/word'
ok result is 'zero/one/two/three/four'
ok Base.static('word') is 'static/word'
FirstChild::func = (string) ->
FirstChild::func = (string) ->
super('one/').length + string
result = (new ThirdChild).func 'four'
result = (new ThirdChild).func 'four'
ok result is '9two/three/four'
ok result is '9two/three/four'
ok (new ThirdChild).array.join(' ') is '1 2 3'
ok (new ThirdChild).array.join(' ') is '1 2 3'
identity = (f) -> f
test "constructors with inheritance and super", ->
class TopClass
identity = (f) -> f
class TopClass
constructor: (arg) ->
@prop = 'top-' + arg
class SuperClass extends TopClass
class SuperClass extends TopClass
constructor: (arg) ->
identity super 'super-' + arg
class SubClass extends SuperClass
class SubClass extends SuperClass
constructor: ->
identity super 'sub'
ok (new SubClass).prop is 'top-super-sub'
ok (new SubClass).prop is 'top-super-sub'
class OneClass
test "Overriding the static property new doesn't clobber Function::new", ->
class OneClass
@new: 'new'
function: 'function'
constructor: (name) -> @name = name
class TwoClass extends OneClass
delete TwoClass.new
class TwoClass extends OneClass
delete TwoClass.new
Function.prototype.new = -> new this arguments...
Function.prototype.new = -> new this arguments...
ok (TwoClass.new('three')).name is 'three'
ok (new OneClass).function is 'function'
ok OneClass.new is 'new'
ok (TwoClass.new('three')).name is 'three'
ok (new OneClass).function is 'function'
ok OneClass.new is 'new'
delete Function.prototype.new
delete Function.prototype.new
# And now the same tests, but written in the manual style:
Base = ->
Base::func = (string) ->
test "basic classes, again, but in the manual prototype style", ->
Base = ->
Base::func = (string) ->
'zero/' + string
Base::['func-func'] = (string) ->
Base::['func-func'] = (string) ->
"dynamic-#{string}"
FirstChild = ->
SecondChild = ->
ThirdChild = ->
FirstChild = ->
SecondChild = ->
ThirdChild = ->
@array = [1, 2, 3]
this
ThirdChild extends SecondChild extends FirstChild extends Base
ThirdChild extends SecondChild extends FirstChild extends Base
FirstChild::func = (string) ->
FirstChild::func = (string) ->
super('one/') + string
SecondChild::func = (string) ->
SecondChild::func = (string) ->
super('two/') + string
ThirdChild::func = (string) ->
ThirdChild::func = (string) ->
super('three/') + string
result = (new ThirdChild).func 'four'
result = (new ThirdChild).func 'four'
ok result is 'zero/one/two/three/four'
ok result is 'zero/one/two/three/four'
ok (new ThirdChild)['func-func']('thing') is 'dynamic-thing'
ok (new ThirdChild)['func-func']('thing') is 'dynamic-thing'
test "super with plain ol' functions as the original constructors", ->
TopClass = (arg) ->
@prop = 'top-' + arg
this
@ -131,40 +137,42 @@ SubClass extends SuperClass
ok (new SubClass).prop is 'top-super-sub'
# '@' referring to the current instance, and not being coerced into a call.
class ClassName
test "'@' referring to the current instance, and not being coerced into a call", ->
class ClassName
amI: ->
@ instanceof ClassName
obj = new ClassName
ok obj.amI()
obj = new ClassName
ok obj.amI()
# super() calls in constructors of classes that are defined as object properties.
class Hive
test "super() calls in constructors of classes that are defined as object properties", ->
class Hive
constructor: (name) -> @name = name
class Hive.Bee extends Hive
class Hive.Bee extends Hive
constructor: (name) -> super
maya = new Hive.Bee 'Maya'
ok maya.name is 'Maya'
maya = new Hive.Bee 'Maya'
ok maya.name is 'Maya'
# Class with JS-keyword properties.
class Class
test "classes with JS-keyword properties", ->
class Class
class: 'class'
name: -> @class
instance = new Class
ok instance.class is 'class'
ok instance.name() is 'class'
instance = new Class
ok instance.class is 'class'
ok instance.name() is 'class'
# Classes with methods that are pre-bound to the instance.
# ... or statically, to the class.
class Dog
test "Classes with methods that are pre-bound to the instance, or statically, to the class", ->
class Dog
constructor: (name) ->
@name = name
@ -174,126 +182,136 @@ class Dog
@static = =>
new this('Dog')
spark = new Dog('Spark')
fido = new Dog('Fido')
fido.bark = spark.bark
spark = new Dog('Spark')
fido = new Dog('Fido')
fido.bark = spark.bark
ok fido.bark() is 'Spark woofs!'
ok fido.bark() is 'Spark woofs!'
obj = func: Dog.static
obj = func: Dog.static
ok obj.func().name is 'Dog'
ok obj.func().name is 'Dog'
# Testing a bound function in a bound function.
class Mini
test "a bound function in a bound function", ->
class Mini
num: 10
generate: =>
for i in [1..3]
=>
@num
m = new Mini
eq (func() for func in m.generate()).join(' '), '10 10 10'
m = new Mini
eq (func() for func in m.generate()).join(' '), '10 10 10'
# Testing a contructor called with varargs.
class Connection
test "contructor called with varargs", ->
class Connection
constructor: (one, two, three) ->
[@one, @two, @three] = [one, two, three]
out: ->
"#{@one}-#{@two}-#{@three}"
list = [3, 2, 1]
conn = new Connection list...
ok conn instanceof Connection
ok conn.out() is '3-2-1'
list = [3, 2, 1]
conn = new Connection list...
ok conn instanceof Connection
ok conn.out() is '3-2-1'
# Test calling super and passing along all arguments.
class Parent
test "calling super and passing along all arguments", ->
class Parent
method: (args...) -> @args = args
class Child extends Parent
class Child extends Parent
method: -> super
c = new Child
c.method 1, 2, 3, 4
ok c.args.join(' ') is '1 2 3 4'
c = new Child
c.method 1, 2, 3, 4
ok c.args.join(' ') is '1 2 3 4'
# Test classes wrapped in decorators.
func = (klass) ->
test "classes wrapped in decorators", ->
func = (klass) ->
klass::prop = 'value'
klass
func class Test
func class Test
prop2: 'value2'
ok (new Test).prop is 'value'
ok (new Test).prop2 is 'value2'
ok (new Test).prop is 'value'
ok (new Test).prop2 is 'value2'
# Test anonymous classes.
obj =
test "anonymous classes", ->
obj =
klass: class
method: -> 'value'
instance = new obj.klass
ok instance.method() is 'value'
instance = new obj.klass
ok instance.method() is 'value'
# Implicit objects as static properties.
class Static
test "Implicit objects as static properties", ->
class Static
@static =
one: 1
two: 2
ok Static.static.one is 1
ok Static.static.two is 2
ok Static.static.one is 1
ok Static.static.two is 2
# Nothing classes.
c = class
ok c instanceof Function
test "nothing classes", ->
c = class
ok c instanceof Function
# Classes with value'd constructors.
counter = 0
classMaker = ->
test "classes with value'd constructors", ->
counter = 0
classMaker = ->
counter++
inner = counter
->
@value = inner
class One
class One
constructor: classMaker()
class Two
class Two
constructor: classMaker()
ok (new One).value is 1
ok (new Two).value is 2
ok (new One).value is 1
ok (new Two).value is 2
ok (new One).value is 1
ok (new Two).value is 2
ok (new One).value is 1
ok (new Two).value is 2
# Exectuable class bodies.
class A
test "exectuable class bodies", ->
class A
if true
b: 'b'
else
c: 'c'
a = new A
a = new A
eq a.b, 'b'
eq a.c, undefined
eq a.b, 'b'
eq a.c, undefined
# Light metaprogramming.
class Base
test "mild metaprogramming", ->
class Base
@attr: (name) ->
@::[name] = (val) ->
if arguments.length > 0
@ -301,38 +319,40 @@ class Base
else
@["_#{name}"]
class Robot extends Base
class Robot extends Base
@attr 'power'
@attr 'speed'
robby = new Robot
robby = new Robot
ok robby.power() is undefined
ok robby.power() is undefined
robby.power 11
robby.speed Infinity
robby.power 11
robby.speed Infinity
eq robby.power(), 11
eq robby.speed(), Infinity
eq robby.power(), 11
eq robby.speed(), Infinity
# Namespaced classes do not reserve their function name in outside scope.
one = {}
two = {}
test "namespaced classes do not reserve their function name in outside scope", ->
class one.Klass
one = {}
two = {}
class one.Klass
@label = "one"
class two.Klass
class two.Klass
@label = "two"
eq typeof Klass, 'undefined'
eq one.Klass.label, 'one'
eq two.Klass.label, 'two'
eq typeof Klass, 'undefined'
eq one.Klass.label, 'one'
eq two.Klass.label, 'two'
# Nested classes.
class Outer
test "nested classes", ->
class Outer
constructor: ->
@label = 'outer'
@ -340,12 +360,13 @@ class Outer
constructor: ->
@label = 'inner'
eq (new Outer).label, 'outer'
eq (new Outer.Inner).label, 'inner'
eq (new Outer).label, 'outer'
eq (new Outer.Inner).label, 'inner'
# Variables in constructor bodies are correctly scoped.
class A
test "variables in constructor bodies are correctly scoped", ->
class A
x = 1
constructor: ->
x = 10
@ -354,60 +375,64 @@ class A
captured: ->
{x, y}
a = new A
eq a.captured().x, 10
eq a.captured().y, 2
a = new A
eq a.captured().x, 10
eq a.captured().y, 2
# Issue #924: Static methods in nested classes.
class A
test "Issue #924: Static methods in nested classes", ->
class A
@B: class
@c = -> 5
eq A.B.c(), 5
eq A.B.c(), 5
# `class extends this` ...
class A
test "`class extends this`", ->
class A
func: -> 'A'
B = null
makeClass = ->
B = null
makeClass = ->
B = class extends this
func: -> super + ' B'
makeClass.call A
makeClass.call A
eq (new B()).func(), 'A B'
eq (new B()).func(), 'A B'
test "ensure that constructors invoked with splats return a new object", ->
args = [1, 2, 3]
Type = (@args) ->
type = new Type args
ok type and type instanceof Type
ok type.args and type.args instanceof Array
ok v is args[i] for v, i in type.args
Type1 = (@a, @b, @c) ->
type1 = new Type1 args...
ok type1 instanceof Type1
eq type1.constructor, Type1
ok type1.a is args[0] and type1.b is args[1] and type1.c is args[2]
# Ensure that constructors invoked with splats cache the function.
called = 0
get = -> if called++ then false else class Type
new get() args...
test "`new` shouldn't add extra parens", ->
ok new Date().constructor is Date
# Ensure that constructors invoked with splats return a new object.
args = [1, 2, 3]
Type = (@args) ->
type = new Type args
test "`new` works against bare function", ->
ok type and type instanceof Type
ok type.args and type.args instanceof Array
ok v is args[i] for v, i in type.args
Type1 = (@a, @b, @c) ->
type1 = new Type1 args...
ok type1 instanceof Type1
eq type1.constructor, Type1
ok type1.a is args[0] and type1.b is args[1] and type1.c is args[2]
# Ensure that constructors invoked with splats cache the function.
called = 0
get = -> if called++ then false else class Type
new get() args...
# `new` shouldn't add extra parens
ok new Date().constructor is Date
# `new` works against bare function
eq Date, new ->
eq Date, new ->
eq this, new => this
Date