cleaning up tests ... consolidation, consistency...

This commit is contained in:
Jeremy Ashkenas 2010-04-03 10:39:32 -04:00
parent f99b5ad463
commit 4a85f3d499
31 changed files with 250 additions and 272 deletions

View File

@ -4,17 +4,17 @@ area: (x, y, x1, y1) ->
x: y: 10
x1: y1: 20
ok area(x, y, x1, y1) is 100, 'basic arguments'
ok area(x, y, x1, y1) is 100
ok(area(x, y,
x1, y1) is 100, 'arguments on split lines')
x1, y1) is 100)
ok(area(
x
y
x1
y1
) is 100, 'newline delimited arguments')
) is 100)
sum_of_args: ->

View File

@ -1,42 +0,0 @@
nums: n * n for n in [1, 2, 3] when n % 2 isnt 0
results: n * 2 for n in nums
ok results.join(',') is '2,18', 'basic array comprehension'
obj: {one: 1, two: 2, three: 3}
names: prop + '!' for prop of obj
odds: prop + '!' for prop, value of obj when value % 2 isnt 0
ok names.join(' ') is "one! two! three!", 'basic object comprehension'
ok odds.join(' ') is "one! three!", 'object comprehension with a filter'
evens: for num in [1, 2, 3, 4, 5, 6] when num % 2 is 0
num *= -1
num -= 2
num * -1
ok evens.join(', ') is '4, 6, 8', 'multiline array comprehension with filter'
ok 2 in evens, 'the in operator still works, standalone'
# Ensure that the closure wrapper preserves local variables.
obj: {}
methods: ['one', 'two', 'three']
for method in methods
name: method
obj[name]: ->
"I'm " + name
ok obj.one() is "I'm one"
ok obj.two() is "I'm two"
ok obj.three() is "I'm three"
array: [0..10]
ok(num % 2 is 0 for num in array by 2, 'naked ranges are expanded into arrays')

View File

@ -1,3 +1,4 @@
# Can assign the result of a try/catch block.
result: try
nonexistent * missing
catch error
@ -5,20 +6,22 @@ catch error
result2: try nonexistent * missing catch error then true
ok result is true and result2 is true, 'can assign the result of a try/catch block'
ok result is true and result2 is true
# Can assign a conditional statement.
get_x: -> 10
if x: get_x() then 100
ok x is 10, 'can assign a conditional statement'
ok x is 10
x: if get_x() then 100
ok x is 100, 'can assign a conditional statement'
ok x is 100
# This-assignment.
tester: ->
@example: -> puts 'example function'
this

View File

@ -1,7 +1,8 @@
# Basic blocks.
results: [1, 2, 3].map (x) ->
x * x
ok results.join(' ') is '1 4 9', 'basic block syntax'
ok results.join(' ') is '1 4 9'
# Chained blocks, with proper indentation levels:

View File

@ -1,25 +0,0 @@
identity_wrap: (x) ->
-> x
result: identity_wrap(identity_wrap(true))()()
ok result, 'basic chained function calls'
str: 'god'
result: str.
split('').
reverse().
reverse().
reverse()
ok result.join('') is 'dog', 'chained accesses split on period/newline'
result: str
.split('')
.reverse()
.reverse()
.reverse()
ok result.join('') is 'dog', 'chained accesses split on newline/period'

36
test/test_chaining.coffee Normal file
View File

@ -0,0 +1,36 @@
# Basic chained function calls.
identity_wrap: (x) ->
-> x
result: identity_wrap(identity_wrap(true))()()
ok result
# Chained accesses split on period/newline, backwards and forwards.
str: 'god'
result: str.
split('').
reverse().
reverse().
reverse()
ok result.join('') is 'dog'
result: str
.split('')
.reverse()
.reverse()
.reverse()
ok result.join('') is 'dog'
# Newline suppression for operators.
six:
1 +
2 +
3
ok six is 6

View File

@ -1,3 +1,4 @@
# Test classes with a four-level inheritance chain.
class Base
func: (string) ->
"zero/$string"
@ -47,4 +48,49 @@ class OneClass
class TwoClass extends OneClass
ok (new TwoClass('three')).name is 'three'
ok (new TwoClass('three')).name is 'three'
# And now the same tests, but written in the manual style:
Base: ->
Base::func: (string) ->
'zero/' + string
FirstChild: ->
FirstChild extends Base
FirstChild::func: (string) ->
super('one/') + string
SecondChild: ->
SecondChild extends FirstChild
SecondChild::func: (string) ->
super('two/') + string
ThirdChild: ->
@array: [1, 2, 3]
this
ThirdChild extends SecondChild
ThirdChild::func: (string) ->
super('three/') + string
result: (new ThirdChild()).func 'four'
ok result is 'zero/one/two/three/four'
TopClass: (arg) ->
@prop: 'top-' + arg
this
SuperClass: (arg) ->
super 'super-' + arg
this
SubClass: ->
super 'sub'
this
SuperClass extends TopClass
SubClass extends SuperClass
ok (new SubClass()).prop is 'top-super-sub'

View File

@ -0,0 +1,94 @@
# Basic array comprehensions.
nums: n * n for n in [1, 2, 3] when n % 2 isnt 0
results: n * 2 for n in nums
ok results.join(',') is '2,18'
# Basic object comprehensions.
obj: {one: 1, two: 2, three: 3}
names: prop + '!' for prop of obj
odds: prop + '!' for prop, value of obj when value % 2 isnt 0
ok names.join(' ') is "one! two! three!"
ok odds.join(' ') is "one! three!"
# Basic range comprehensions.
nums: i * 3 for i in [1..3]
negs: x for x in [-20..-5*2]
negs: negs[0..2]
result: nums.concat(negs).join(', ')
ok result is '3, 6, 9, -20, -19, -18'
# Ensure that ranges are safe. This used to infinite loop:
j = 5
result: for j in [j..(j+3)]
j
ok result.join(' ') is '5 6 7 8'
# With range comprehensions, you can loop in steps.
results: x for x in [0..25] by 5
ok results.join(' ') is '0 5 10 15 20 25'
# Multiline array comprehension with filter.
evens: for num in [1, 2, 3, 4, 5, 6] when num % 2 is 0
num *= -1
num -= 2
num * -1
ok evens.join(', ') is '4, 6, 8'
# The in operator still works, standalone.
ok 2 in evens
# Ensure that the closure wrapper preserves local variables.
obj: {}
methods: ['one', 'two', 'three']
for method in methods
name: method
obj[name]: ->
"I'm " + name
ok obj.one() is "I'm one"
ok obj.two() is "I'm two"
ok obj.three() is "I'm three"
# Naked ranges are expanded into arrays.
array: [0..10]
ok(num % 2 is 0 for num in array by 2)
# Nested comprehensions.
multi_liner:
for x in [3..5]
for y in [3..5]
[x, y]
single_liner:
[x, y] for y in [3..5] for x in [3..5]
ok multi_liner.length is single_liner.length
ok 5 is multi_liner[2][2][1]
ok 5 is single_liner[2][2][1]
# Comprehensions within parentheses.
result: null
store: (obj) -> result: obj
store (x * 2 for x in [3, 2, 1])
ok result.join(' ') is '6 4 2'

View File

@ -1,31 +0,0 @@
func: ->
a: 3
b: []
while a >= 0
b.push 'o'
a--
c: {
"text": b
other: null
something_else: (x) -> x + 5
}
c: 'error' unless 42 > 41
c.text: if false
'error'
else
c.text + '---'
d = {
text = c.text
}
c.list: l for l in d.text.split('') when l is '-'
c.single: c.list[1..1][0]
ok func() is '-'

View File

@ -1,2 +1,19 @@
# Basic exception throwing.
block: -> (throw 'up')
throws block, 'up'
throws block, 'up'
# Basic try/catch.
result: try
10
finally
15
ok result is 10
result: try
throw 'up'
catch err
err.length
ok result is 2

View File

@ -6,7 +6,6 @@ ok(if my_special_variable? then true else false)
# Existential assignment.
a: 5
a: null
a ?= 10
@ -16,7 +15,6 @@ ok a is 10 and b is 10
# The existential operator.
z: null
x: z ? "EX"
@ -24,7 +22,6 @@ ok z is null and x is "EX"
# Only evaluate once.
counter: 0
get_next_node: ->
throw "up" if counter
@ -34,7 +31,6 @@ ok(if get_next_node()? then true else false)
# Existence chains, soaking up undefined properties:
obj: {
prop: "hello"
}
@ -53,7 +49,6 @@ ok obj?['non']?['existent'].property is undefined
# Soaks and caches method calls as well.
arr: ["--", "----"]
ok arr.pop()?.length is 4

View File

@ -1,5 +1,4 @@
# Ensure that we don't wrap Nodes that are "pure_statement" in a closure.
items: [1, 2, 3, "bacon", 4, 5]
for item in items
@ -14,7 +13,6 @@ ok findit(items) is "bacon"
# When when a closure wrapper is generated for expression conversion, make sure
# that references to "this" within the wrapper are safely converted as well.
obj: {
num: 5
func: ->

View File

@ -129,16 +129,3 @@ result: (f 1).toString()
.length
ok result is 1
# Test that `this` is "callable".
obj: {
greet: (salutation) ->
"Hello $salutation"
hello: ->
this['greet'] "You"
}
ok obj.hello() is 'Hello You'

View File

@ -27,8 +27,6 @@ ok result
# If statement with a comment-only clause.
result: if false
# comment
else

View File

@ -1,2 +1,2 @@
# Check if it can import and execute a coffeescript-only module successfully.
# Check if we can import and execute a CoffeeScript-only module successfully.
ok require('./test_module').func() is "from over there"

View File

@ -1,10 +0,0 @@
num: 1 + 2 + (a: 3)
ok num is 6
result: if true
false
other: "result"
ok result is "result" and other is "result"

View File

@ -53,8 +53,8 @@ ok multiline is 'one two three'
ok {a: (num) -> num is 10 }.a 10
bob: {
name: 'Bob'
moe: {
name: 'Moe'
greet: (salutation) ->
salutation + " " + @name
hello: ->
@ -62,8 +62,13 @@ bob: {
10: 'number'
}
ok bob.hello() is "Hello Bob"
ok bob[10] is 'number'
ok moe.hello() is "Hello Moe"
ok moe[10] is 'number'
moe.hello: ->
this['greet'] "Hello"
ok moe.hello() is 'Hello Moe'
obj: {

View File

@ -1,20 +0,0 @@
multi_liner:
for x in [3..5]
for y in [3..5]
[x, y]
single_liner:
[x, y] for y in [3..5] for x in [3..5]
ok multi_liner.length is single_liner.length
ok 5 is multi_liner[2][2][1]
ok 5 is single_liner[2][2][1]
# Test comprehensions within parentheses.
result: null
store: (obj) -> result: obj
store (x * 2 for x in [3, 2, 1])
ok result.join(' ') is '6 4 2'

View File

@ -1,6 +0,0 @@
six:
1 +
2 +
3
ok six is 6

View File

@ -1,42 +0,0 @@
Base: ->
Base::func: (string) ->
'zero/' + string
FirstChild: ->
FirstChild extends Base
FirstChild::func: (string) ->
super('one/') + string
SecondChild: ->
SecondChild extends FirstChild
SecondChild::func: (string) ->
super('two/') + string
ThirdChild: ->
@array: [1, 2, 3]
this
ThirdChild extends SecondChild
ThirdChild::func: (string) ->
super('three/') + string
result: (new ThirdChild()).func 'four'
ok result is 'zero/one/two/three/four', 'successfully set up and called a four-level inheritance chain'
TopClass: (arg) ->
@prop: 'top-' + arg
this
SuperClass: (arg) ->
super 'super-' + arg
this
SubClass: ->
super 'sub'
this
SuperClass extends TopClass
SubClass extends SuperClass
ok (new SubClass()).prop is 'top-super-sub', 'inheritance'

View File

@ -1,5 +1,4 @@
# CoffeeScript's operations should be chainable, like Python's.
ok 500 > 50 > 5 > -5
ok true is not false is true is not false
@ -13,7 +12,6 @@ ok 50 > 10 > 5 is parseInt('5', 10)
# Make sure that each argument is only evaluated once, even if used
# more than once.
i: 0
func: -> i++
@ -21,7 +19,6 @@ ok 1 > func() < 1
# `:` and `=` should be interchangeable, as should be `==` and `is`.
a: 1
b: 1
@ -32,7 +29,6 @@ ok a is b
# Ensure that chained operations don't cause functions to be evaluated more
# than once.
val: 0
func: -> val: + 1

View File

@ -1,3 +1,4 @@
# Simple variable swapping.
a: -1
b: -2
@ -6,13 +7,11 @@ b: -2
ok a is -2
ok b is -1
func: ->
[a, b]: [b, a]
ok func().join(' ') is '-1 -2'
noop: ->
noop [a,b]: [c,d]: [1,2]
@ -20,6 +19,7 @@ noop [a,b]: [c,d]: [1,2]
ok a is 1 and b is 2
# Array destructuring, including splats.
arr: [1, 2, 3]
[a, b, c]: arr
@ -43,6 +43,8 @@ ok last is 40
ok z.length is 3 and z[2] is 4
ok end is 5
# Object destructuring.
obj: {x: 10, y: 20, z: 30}
{x: a, y: b, z: c}: obj
@ -51,9 +53,8 @@ ok a is 10
ok b is 20
ok c is 30
person: {
name: "Bob"
name: "Moe"
family: {
brother: {
addresses: [
@ -69,10 +70,9 @@ person: {
{name: a, family: {brother: {addresses: [one, {city: b}]}}}: person
ok a is "Bob"
ok a is "Moe"
ok b is "Moquasset NY, 10021"
test: {
person: {
address: [
@ -89,6 +89,7 @@ test: {
ok addr.join(', ') is "Street 101, Apt 101, City 101"
# Destructuring against an expression.
[a, b]: if true then [2, 1] else [1, 2]
ok a is 2

View File

@ -1,20 +0,0 @@
nums: i * 3 for i in [1..3]
negs: x for x in [-20..-5*2]
negs: negs[0..2]
result: nums.concat(negs).join(', ')
ok result is '3, 6, 9, -20, -19, -18'
# Ensure that ranges are safe. This used to infinite loop:
j = 5
result: for j in [j..(j+3)]
j
ok result.join(' ') is '5 6 7 8'
# With range comprehensions, you can loop in steps.
results: x for x in [0..25] by 5
ok results.join(' ') is '0 5 10 15 20 25'

View File

@ -1,3 +1,4 @@
# Slice.
array: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
a: array[7..9]
@ -7,15 +8,21 @@ result: a.concat(b).join(' ')
ok result is "7 8 9 2 3"
a: [0, 1, 2, 3, 4, 5, 6, 7]
deepEqual a[2...6], [2, 3, 4, 5]
# Range.
countdown: [10..1].join(' ')
ok countdown is "10 9 8 7 6 5 4 3 2 1"
# Expression-based range.
array: [(1+5)..1+9]
ok array.join(' ') is "6 7 8 9 10"
# String slicing (at least on Node).
hello: "Hello World"
ok hello[1...1] is ""
@ -23,6 +30,12 @@ ok hello[1..1] is "e"
ok hello[1...5] is "ello"
ok hello[0..4] is "Hello"
a: [0, 1, 2, 3, 4, 5, 6, 7]
deepEqual a[2...6], [2, 3, 4, 5]
# Splice literals.
array: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
array[5..10]: [0, 0, 0]
ok array.join(' ') is '0 1 2 3 4 0 0 0'

View File

@ -1,12 +1,13 @@
name: 'Bob'
# Interpolate regular expressions.
name: 'Moe'
ok not not '"Bob"'.match(/^"${name}"$/i)
ok '"Bobby"'.match(/^"${name}"$/i) is null
ok not not '"Moe"'.match(/^"${name}"$/i)
ok '"Moe!"'.match(/^"${name}"$/i) is null
ok not not 'Bob'.match(/^$name$/)
ok 'Bobby'.match(/^$name/)
ok not not 'Moe'.match(/^$name$/)
ok 'Moe!'.match(/^$name/)
ok 'Bobby'.match(/${"${"${"$name"}"}"}/imgy)
ok 'Moe!'.match(/${"${"${"$name"}"}"}/imgy)
ok '$a$b$c'.match(/\$A\$B\$C/i)

View File

@ -1,3 +1,4 @@
# Regular expression literals.
ok 'x'.match(/x/g)
ok 'x'.match /x/g
ok 'x'.match(/x/)

View File

@ -1,3 +1,4 @@
# Expression conversion under explicit returns.
first: ->
return 'do' for x in [1,2,3]

View File

@ -45,12 +45,12 @@ ok bronze is "Mighty Mouse"
ok last is "Michael Phelps"
ok the_field.length is 8
medalists contenders..., 'Tim', 'Bob', 'Jim'
medalists contenders..., 'Tim', 'Moe', 'Jim'
ok last is 'Jim'
obj: {
name: 'bob'
name: 'moe'
accessor: (args...) ->
[@name].concat(args).join(' ')
getNames: ->
@ -58,7 +58,7 @@ obj: {
@accessor(args...)
}
ok obj.getNames() is 'bob jane ted'
ok obj.getNames() is 'moe jane ted'
crowd: [

View File

@ -1,5 +0,0 @@
array: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
array[5..10]: [0, 0, 0]
ok array.join(' ') is '0 1 2 3 4 0 0 0'

View File

@ -1,14 +0,0 @@
result: try
10
finally
15
ok result is 10
result: try
throw 'up'
catch err
err.length
ok result is 2