asds/} />;
+ '''
+
+test 'string attribute', ->
+ eqJS '''
+
+ ''', '''
+
;
+ '''
+
+test 'simple attribute', ->
+ eqJS '''
+
+ ''', '''
+
;
+ '''
+
+test 'assignment attribute', ->
+ eqJS '''
+
+ ''', '''
+ var y;
+
+
;
+ '''
+
+test 'object attribute', ->
+ eqJS '''
+
+ ''', '''
+
;
+ '''
+
+test 'attribute without value', ->
+ eqJS '''
+
+ ''', '''
+
;
+ '''
+
+test 'paired', ->
+ eqJS '''
+
+ ''', '''
+
;
+ '''
+
+test 'simple content', ->
+ eqJS '''
+
Hello world
+ ''', '''
+
Hello world
;
+ '''
+
+test 'content interpolation', ->
+ eqJS '''
+
Hello {42}
+ ''', '''
+
Hello {42}
;
+ '''
+
+test 'nested tag', ->
+ eqJS '''
+
+ ''', '''
+
;
+ '''
+
+test 'tag inside interpolation formatting', ->
+ eqJS '''
+
Hello {}
+ ''', '''
+
Hello
;
+ '''
+
+test 'tag inside interpolation, tags are callable', ->
+ eqJS '''
+
Hello { x}
+ ''', '''
+
Hello {(x)}
;
+ '''
+
+test 'tags inside interpolation, tags trigger implicit calls', ->
+ eqJS '''
+
Hello {f }
+ ''', '''
+
Hello {f()}
;
+ '''
+
+test 'regex in interpolation', ->
+ eqJS '''
+
+ ''', '''
+
;
+ '''
+
+test 'interpolation in string attribute value', ->
+ eqJS '''
+
+ ''', '''
+
;
+ '''
+
+# Unlike in `coffee-react-transform`.
+test 'bare numbers not allowed', ->
+ throws -> CoffeeScript.compile '
'
+
+test 'bare expressions not allowed', ->
+ throws -> CoffeeScript.compile '
'
+
+test 'bare complex expressions not allowed', ->
+ throws -> CoffeeScript.compile '
'
+
+test 'unescaped opening tag angle bracket disallowed', ->
+ throws -> CoffeeScript.compile '
<<'
+
+test 'space around equal sign', ->
+ eqJS '''
+
+ ''', '''
+
;
+ '''
+
+# The following tests were adopted from James Friend’s
+# [https://github.com/jsdf/coffee-react-transform](https://github.com/jsdf/coffee-react-transform).
+
+test 'ambiguous tag-like expression', ->
+ throws -> CoffeeScript.compile 'x = a
c'
+
+test 'ambiguous tag', ->
+ eqJS '''
+ a c
+ ''', '''
+ a( c );
+ '''
+
+test 'escaped CoffeeScript attribute', ->
+ eqJS '''
+
+ ''', '''
+ ;
+ '''
+
+test 'escaped CoffeeScript attribute over multiple lines', ->
+ eqJS '''
+
+ ''', '''
+ ;
+ '''
+
+test 'multiple line escaped CoffeeScript with nested CSX', ->
+ eqJS '''
+
+ {
+
+ for n in a
+
+ }
+
+
+ ''', '''
+ var n;
+
+
+ {(function() {
+ var i, len, results;
+ results = [];
+ for (i = 0, len = a.length; i < len; i++) {
+ n = a[i];
+ results.push();
+ }
+ return results;
+ })()}
+
+ ;
+ '''
+
+test 'nested CSX within an attribute, with object attr value', ->
+ eqJS '''
+
+ } />
+
+ ''', '''
+
+ } />
+ ;
+ '''
+
+test 'complex nesting', ->
+ eqJS '''
+
+ ''', '''
+ ;
+ '''
+
+test 'multiline tag with nested CSX within an attribute', ->
+ eqJS '''
+
+ }
+ >
+ blah blah blah
+
+ ''', '''
+ var name;
+
+ }>
+ blah blah blah
+ ;
+ '''
+
+test 'escaped CoffeeScript with nested object literals', ->
+ eqJS '''
+
+ blah blah blah {
+ {'a' : {}, 'asd': 'asd'}
+ }
+
+ ''', '''
+
+ blah blah blah {{
+ 'a': {},
+ 'asd': 'asd'
+ }}
+ ;
+ '''
+
+test 'multiline tag attributes with escaped CoffeeScript', ->
+ eqJS '''
+
+ ''', '''
+ ;
+ '''
+
+test 'lots of attributes', ->
+ eqJS '''
+
+ ''', '''
+ ;
+ '''
+
+# TODO: fix partially indented CSX
+# test 'multiline elements', ->
+# eqJS '''
+#
+# test = /432/gm # this is a regex
+# 6 /432/gm # this is division
+# }
+# >
+#
+#
+# ''', '''
+# bla
+# '''
+
+test 'complex regex', ->
+ eqJS '''
+
+ /\\/\\/\\>\\//
+ ''', '''
+ ;
+
+ /\\/\\/\\>\\//;
+ '''
+
+test 'heregex', ->
+ eqJS '''
+ test = /432/gm # this is a regex
+ 6 /432/gm # this is division
+
+ {test = //} this is a regex containing something which looks like a tag
+
+
+ REGEX = /// ^
+ (/ (?! [\s=] ) # comment comment comment
+ [^ [ / \n \\ ]* # comment comment
+ (?:
+
+ (?: \\[\s\S] # comment comment
+ | \[ # comment comment
+ [^ \] \n \\ ]*
+ (?: \\[\s\S] [^ \] \n \\ ]* )*
+ tag
+ ]
+ ) [^ [ / \n \\ ]*
+ )*
+ /) ([imgy]{0,4}) (?!\w)
+ ///
+
+ ''', '''
+ var REGEX, test;
+
+ test = /432/gm;
+
+ 6 / 432 / gm;
+
+
+ {(test = //)} this is a regex containing something which looks like a tag
+ ;
+
+ ;
+
+ REGEX = /^(\\/(?![s=])[^[\\/ ]*(?:(?:\\[sS]|[[^] ]*(?:\\[sS][^] ]*)*tag<\\/Tag>])[^[\\/ ]*)*\\/)([imgy]{0,4})(?!w)/;
+
+ ;
+ '''
+
+test 'comment within CSX is not treated as comment', ->
+ eqJS '''
+
+ # i am not a comment
+
+ ''', '''
+
+ # i am not a comment
+ ;
+ '''
+
+test 'comment at start of CSX escape', ->
+ eqJS '''
+
+ {# i am a comment
+ "i am a string"
+ }
+
+ ''', '''
+
+ {"i am a string"}
+ ;
+ '''
+
+test 'CSX comment cannot be used inside interpolation', ->
+ throws -> CoffeeScript.compile '''
+
+ {# i am a comment}
+
+ '''
+
+test 'comment syntax cannot be used inline', ->
+ throws -> CoffeeScript.compile '''
+ {#comment inline}
+ '''
+
+test 'string within CSX is ignored', ->
+ eqJS '''
+ "i am not a string" 'nor am i'
+ ''', '''
+ "i am not a string" 'nor am i' ;
+ '''
+
+test 'special chars within CSX are ignored', ->
+ eqJS """
+ a,/';][' a\''@$%^&˚¬∑˜˚∆å∂¬˚*()*&^%$>> '"''"'''\'\'m' i
+ """, """
+ a,/';][' a''@$%^&˚¬∑˜˚∆å∂¬˚*()*&^%$>> '"''"'''''m' i ;
+ """
+
+test 'html entities (name, decimal, hex) within CSX', ->
+ eqJS '''
+ &&&€ € €;;
+ ''', '''
+ &&&€ € €;; ;
+ '''
+
+test 'tag with {{}}', ->
+ eqJS '''
+
+ ''', '''
+ ;
+ '''
+
+test 'tag with namespace', ->
+ eqJS '''
+
+ ''', '''
+ ;
+ '''
+
+test 'tag with lowercase namespace', ->
+ eqJS '''
+
+ ''', '''
+ ;
+ '''
+
+test 'self closing tag with namespace', ->
+ eqJS '''
+
+ ''', '''
+ ;
+ '''
+
+# TODO: Uncomment the following test once destructured object spreads are supported.
+# test 'self closing tag with spread attribute', ->
+# eqJS '''
+#
+# ''', '''
+# React.createElement(Component, Object.assign({"a": (b)}, x , {"b": "c"}))
+# '''
+
+# TODO: Uncomment the following test once destructured object spreads are supported.
+# test 'complex spread attribute', ->
+# eqJS '''
+#
+# ''', '''
+# React.createElement(Component, Object.assign({}, x, {"a": (b)}, x , {"b": "c"}, $my_xtraCoolVar123 ))
+# '''
+
+# TODO: Uncomment the following test once destructured object spreads are supported.
+# test 'multiline spread attribute', ->
+# eqJS '''
+#
+#
+# ''', '''
+# React.createElement(Component, Object.assign({},
+# x , {"a": (b)}, x , {"b": "c"}, z )
+# )
+# '''
+
+# TODO: Uncomment the following test once destructured object spreads are supported.
+# test 'multiline tag with spread attribute', ->
+# eqJS '''
+#
+#
+# ''', '''
+# React.createElement(Component, Object.assign({ \
+# "z": "1"
+# }, x, { \
+# "a": (b), \
+# "b": "c"
+# })
+# )
+# '''
+
+# TODO: Uncomment the following test once destructured object spreads are supported.
+# test 'multiline tag with spread attribute first', ->
+# eqJS '''
+#
+#
+# ''', '''
+# React.createElement(Component, Object.assign({}, \
+
+# x, { \
+# "z": "1", \
+# "a": (b), \
+# "b": "c"
+# })
+# )
+# '''
+
+# TODO: Uncomment the following test once destructured object spreads are supported.
+# test 'complex multiline spread attribute', ->
+# eqJS '''
+#
+#
+#
+# ''', '''
+# React.createElement(Component, Object.assign({}, \
+
+# y, {"a": (b)}, x , {"b": "c"}, z ),
+# React.createElement("div", {"code": (someFunc({a:{b:{}, C:'}'}}))})
+# )
+# '''
+
+# TODO: Uncomment the following test once destructured object spreads are supported.
+# test 'self closing spread attribute on single line', ->
+# eqJS '''
+#
+# ''', '''
+# React.createElement(Component, Object.assign({"a": "b", "c": "d"}, @props ))
+# '''
+
+# TODO: Uncomment the following test once destructured object spreads are supported.
+# test 'self closing spread attribute on new line', ->
+# eqJS '''
+#
+# ''', '''
+# React.createElement(Component, Object.assign({ \
+# "a": "b", \
+# "c": "d"
+# }, @props
+# ))
+# '''
+
+# TODO: Uncomment the following test once destructured object spreads are supported.
+# test 'self closing spread attribute on same line', ->
+# eqJS '''
+#
+# ''', '''
+# React.createElement(Component, Object.assign({ \
+# "a": "b", \
+# "c": "d"
+# }, @props ))
+# '''
+
+# TODO: Uncomment the following test once destructured object spreads are supported.
+# test 'self closing spread attribute on next line', ->
+# eqJS '''
+#
+# ''', '''
+# React.createElement(Component, Object.assign({ \
+# "a": "b", \
+# "c": "d"
+# }, @props
+
+# ))
+# '''
+
+test 'empty strings are not converted to true', ->
+ eqJS '''
+
+ ''', '''
+ ;
+ '''
+
+test 'CoffeeScript @ syntax in tag name', ->
+ throws -> CoffeeScript.compile '''
+ <@Component>
+
+ @Component>
+ '''
+
+test 'hyphens in tag names', ->
+ eqJS '''
+ {text}
+ ''', '''
+ {text};
+ '''
+
+test 'closing tags must be closed', ->
+ throws -> CoffeeScript.compile '''
+
+ a = 3
+ div = 5
+ ok a
+ div = 5
+ ok 3
+ div = 5
+ ok (3)
+ div = 5
+ a = [3]
+ ok a[0]
+ eqJS '''
+
a
+ ''', '''
+
a;
+ '''
+
+test 'tag inside CSX works following: number', ->
+ eqJS '''
+
3
+ ''', '''
+
3;
+ '''
+
+test 'tag inside CSX works following: paren', ->
+ eqJS '''
+
(3)
+ ''', '''
+
(3);
+ '''
+
+test 'tag inside CSX works following: square bracket', ->
+ eqJS '''
+
]
+ ''', '''
+
];
+ '''
+
+test 'unspaced less than inside CSX works but is not encouraged', ->
+ eqJS '''
+ a = 3
+ div = 5
+ html =
{a
+ ''', '''
+ var a, div, html;
+
+ a = 3;
+
+ div = 5;
+
+ html =
{a < div};
+ '''
+
+test 'unspaced less than before CSX works but is not encouraged', ->
+ eqJS '''
+ div = 5
+ res = 2
+ ''', '''
+ var div, html, res;
+
+ div = 5;
+
+ res = 2 < div;
+
+ html =
;
+ '''
+
+test 'unspaced less than after CSX works but is not encouraged', ->
+ eqJS '''
+ div = 5
+ html =
+ res = 2
;
+
+ res = 2 < div;
+ '''
diff --git a/test/error_messages.coffee b/test/error_messages.coffee
index 63a1d4edaa..5d80637744 100644
--- a/test/error_messages.coffee
+++ b/test/error_messages.coffee
@@ -1545,3 +1545,43 @@ test "#4248: Unicode code point escapes", ->
'\\u{a}\\u{1111110000}'
\ ^\^^^^^^^^^^^^^
'''
+
+test "CSX error: non-matching tag names", ->
+ assertErrorFormat '''
+
+ ''',
+ '''
+ [stdin]:1:7: error: expected corresponding CSX closing tag for span
+
+ ^^^^
+ '''
+
+test "CSX error: bare expressions not allowed", ->
+ assertErrorFormat '''
+
+ ''',
+ '''
+ [stdin]:1:8: error: expected wrapped or quoted CSX attribute
+
+ ^
+ '''
+
+test "CSX error: unescaped opening tag angle bracket disallowed", ->
+ assertErrorFormat '''
+
<<
+ ''',
+ '''
+ [stdin]:1:9: error: unexpected <<
+
<<
+ ^^
+ '''
+
+test "CSX error: ambiguous tag-like expression", ->
+ assertErrorFormat '''
+ x = a
c
+ ''',
+ '''
+ [stdin]:1:10: error: missing
+ x = a c
+ ^
+ '''
diff --git a/test/modules.coffee b/test/modules.coffee
index b662ed68b7..e04c3669a6 100644
--- a/test/modules.coffee
+++ b/test/modules.coffee
@@ -39,80 +39,72 @@
# Import statements
test "backticked import statement", ->
- input = """
+ eqJS """
if Meteor.isServer
- `import { foo, bar as baz } from 'lib'`"""
- output = """
+ `import { foo, bar as baz } from 'lib'`""",
+ """
if (Meteor.isServer) {
import { foo, bar as baz } from 'lib';
}"""
- eq toJS(input), output
test "import an entire module for side effects only, without importing any bindings", ->
- input = "import 'lib'"
- output = "import 'lib';"
- eq toJS(input), output
+ eqJS "import 'lib'",
+ "import 'lib';"
test "import default member from module, adding the member to the current scope", ->
- input = """
+ eqJS """
import foo from 'lib'
- foo.fooMethod()"""
- output = """
+ foo.fooMethod()""",
+ """
import foo from 'lib';
foo.fooMethod();"""
- eq toJS(input), output
test "import an entire module's contents as an alias, adding the alias to the current scope", ->
- input = """
+ eqJS """
import * as foo from 'lib'
- foo.fooMethod()"""
- output = """
+ foo.fooMethod()""",
+ """
import * as foo from 'lib';
foo.fooMethod();"""
- eq toJS(input), output
test "import empty object", ->
- input = "import { } from 'lib'"
- output = "import {} from 'lib';"
- eq toJS(input), output
+ eqJS "import { } from 'lib'",
+ "import {} from 'lib';"
test "import empty object", ->
- input = "import {} from 'lib'"
- output = "import {} from 'lib';"
- eq toJS(input), output
+ eqJS "import {} from 'lib'",
+ "import {} from 'lib';"
test "import a single member of a module, adding the member to the current scope", ->
- input = """
+ eqJS """
import { foo } from 'lib'
- foo.fooMethod()"""
- output = """
+ foo.fooMethod()""",
+ """
import {
foo
} from 'lib';
foo.fooMethod();"""
- eq toJS(input), output
test "import a single member of a module as an alias, adding the alias to the current scope", ->
- input = """
+ eqJS """
import { foo as bar } from 'lib'
- bar.barMethod()"""
- output = """
+ bar.barMethod()""",
+ """
import {
foo as bar
} from 'lib';
bar.barMethod();"""
- eq toJS(input), output
test "import multiple members of a module, adding the members to the current scope", ->
- input = """
+ eqJS """
import { foo, bar } from 'lib'
foo.fooMethod()
- bar.barMethod()"""
- output = """
+ bar.barMethod()""",
+ """
import {
foo,
bar
@@ -121,14 +113,13 @@ test "import multiple members of a module, adding the members to the current sco
foo.fooMethod();
bar.barMethod();"""
- eq toJS(input), output
test "import multiple members of a module where some are aliased, adding the members or aliases to the current scope", ->
- input = """
+ eqJS """
import { foo, bar as baz } from 'lib'
foo.fooMethod()
- baz.bazMethod()"""
- output = """
+ baz.bazMethod()""",
+ """
import {
foo,
bar as baz
@@ -137,15 +128,14 @@ test "import multiple members of a module where some are aliased, adding the mem
foo.fooMethod();
baz.bazMethod();"""
- eq toJS(input), output
test "import default member and other members of a module, adding the members to the current scope", ->
- input = """
+ eqJS """
import foo, { bar, baz as qux } from 'lib'
foo.fooMethod()
bar.barMethod()
- qux.quxMethod()"""
- output = """
+ qux.quxMethod()""",
+ """
import foo, {
bar,
baz as qux
@@ -156,87 +146,80 @@ test "import default member and other members of a module, adding the members to
bar.barMethod();
qux.quxMethod();"""
- eq toJS(input), output
test "import default member from a module as well as the entire module's contents as an alias, adding the member and alias to the current scope", ->
- input = """
+ eqJS """
import foo, * as bar from 'lib'
foo.fooMethod()
- bar.barMethod()"""
- output = """
+ bar.barMethod()""",
+ """
import foo, * as bar from 'lib';
foo.fooMethod();
bar.barMethod();"""
- eq toJS(input), output
test "multiline simple import", ->
- input = """
+ eqJS """
import {
foo,
bar as baz
- } from 'lib'"""
- output = """
+ } from 'lib'""",
+ """
import {
foo,
bar as baz
} from 'lib';"""
- eq toJS(input), output
test "multiline complex import", ->
- input = """
+ eqJS """
import foo, {
bar,
baz as qux
- } from 'lib'"""
- output = """
+ } from 'lib'""",
+ """
import foo, {
bar,
baz as qux
} from 'lib';"""
- eq toJS(input), output
test "import with optional commas", ->
- input = "import { foo, bar, } from 'lib'"
- output = """
+ eqJS "import { foo, bar, } from 'lib'",
+ """
import {
foo,
bar
} from 'lib';"""
- eq toJS(input), output
test "multiline import without commas", ->
- input = """
+ eqJS """
import {
foo
bar
- } from 'lib'"""
- output = """
+ } from 'lib'""",
+ """
import {
foo,
bar
} from 'lib';"""
- eq toJS(input), output
test "multiline import with optional commas", ->
- input = """
+ eqJS """
import {
foo,
bar,
- } from 'lib'"""
- output = """
+ } from 'lib'""",
+ """
import {
foo,
bar
} from 'lib';"""
- eq toJS(input), output
test "a variable can be assigned after an import", ->
- input = """
+ eqJS """
import { foo } from 'lib'
- bar = 5"""
- output = """
+ bar = 5""",
+ """
var bar;
import {
@@ -244,14 +227,13 @@ test "a variable can be assigned after an import", ->
} from 'lib';
bar = 5;"""
- eq toJS(input), output
test "variables can be assigned before and after an import", ->
- input = """
+ eqJS """
foo = 5
import { bar } from 'lib'
- baz = 7"""
- output = """
+ baz = 7""",
+ """
var baz, foo;
foo = 5;
@@ -261,185 +243,164 @@ test "variables can be assigned before and after an import", ->
} from 'lib';
baz = 7;"""
- eq toJS(input), output
# Export statements
test "export empty object", ->
- input = "export { }"
- output = "export {};"
- eq toJS(input), output
+ eqJS "export { }",
+ "export {};"
test "export empty object", ->
- input = "export {}"
- output = "export {};"
- eq toJS(input), output
+ eqJS "export {}",
+ "export {};"
test "export named members within an object", ->
- input = "export { foo, bar }"
- output = """
+ eqJS "export { foo, bar }",
+ """
export {
foo,
bar
};"""
- eq toJS(input), output
test "export named members as aliases, within an object", ->
- input = "export { foo as bar, baz as qux }"
- output = """
+ eqJS "export { foo as bar, baz as qux }",
+ """
export {
foo as bar,
baz as qux
};"""
- eq toJS(input), output
test "export named members within an object, with an optional comma", ->
- input = "export { foo, bar, }"
- output = """
+ eqJS "export { foo, bar, }",
+ """
export {
foo,
bar
};"""
- eq toJS(input), output
test "multiline export named members within an object", ->
- input = """
+ eqJS """
export {
foo,
bar
- }"""
- output = """
+ }""",
+ """
export {
foo,
bar
};"""
- eq toJS(input), output
test "multiline export named members within an object, with an optional comma", ->
- input = """
+ eqJS """
export {
foo,
bar,
- }"""
- output = """
+ }""",
+ """
export {
foo,
bar
};"""
- eq toJS(input), output
test "export default string", ->
- input = "export default 'foo'"
- output = "export default 'foo';"
- eq toJS(input), output
+ eqJS "export default 'foo'",
+ "export default 'foo';"
test "export default number", ->
- input = "export default 5"
- output = "export default 5;"
- eq toJS(input), output
+ eqJS "export default 5",
+ "export default 5;"
test "export default object", ->
- input = "export default { foo: 'bar', baz: 'qux' }"
- output = """
+ eqJS "export default { foo: 'bar', baz: 'qux' }",
+ """
export default {
foo: 'bar',
baz: 'qux'
};"""
- eq toJS(input), output
test "export default implicit object", ->
- input = "export default foo: 'bar', baz: 'qux'"
- output = """
+ eqJS "export default foo: 'bar', baz: 'qux'",
+ """
export default {
foo: 'bar',
baz: 'qux'
};"""
- eq toJS(input), output
test "export default multiline implicit object", ->
- input = """
+ eqJS """
export default
foo: 'bar',
baz: 'qux'
- """
- output = """
+ """,
+ """
export default {
foo: 'bar',
baz: 'qux'
};"""
- eq toJS(input), output
test "export default assignment expression", ->
- input = "export default foo = 'bar'"
- output = """
+ eqJS "export default foo = 'bar'",
+ """
var foo;
export default foo = 'bar';"""
- eq toJS(input), output
test "export assignment expression", ->
- input = "export foo = 'bar'"
- output = "export var foo = 'bar';"
- eq toJS(input), output
+ eqJS "export foo = 'bar'",
+ "export var foo = 'bar';"
test "export multiline assignment expression", ->
- input = """
+ eqJS """
export foo =
- 'bar'"""
- output = "export var foo = 'bar';"
- eq toJS(input), output
+ 'bar'""",
+ "export var foo = 'bar';"
test "export multiline indented assignment expression", ->
- input = """
+ eqJS """
export foo =
- 'bar'"""
- output = "export var foo = 'bar';"
- eq toJS(input), output
+ 'bar'""",
+ "export var foo = 'bar';"
test "export default function", ->
- input = "export default ->"
- output = "export default function() {};"
- eq toJS(input), output
+ eqJS "export default ->",
+ "export default function() {};"
test "export default multiline function", ->
- input = """
+ eqJS """
export default (foo) ->
- console.log foo"""
- output = """
+ console.log foo""",
+ """
export default function(foo) {
return console.log(foo);
};"""
- eq toJS(input), output
test "export assignment function", ->
- input = """
+ eqJS """
export foo = (bar) ->
- console.log bar"""
- output = """
+ console.log bar""",
+ """
export var foo = function(bar) {
return console.log(bar);
};"""
- eq toJS(input), output
test "export assignment function which contains assignments in its body", ->
- input = """
+ eqJS """
export foo = (bar) ->
baz = '!'
- console.log bar + baz"""
- output = """
+ console.log bar + baz""",
+ """
export var foo = function(bar) {
var baz;
baz = '!';
return console.log(bar + baz);
};"""
- eq toJS(input), output
test "export default predefined function", ->
- input = """
+ eqJS """
foo = (bar) ->
console.log bar
- export default foo"""
- output = """
+ export default foo""",
+ """
var foo;
foo = function(bar) {
@@ -447,14 +408,13 @@ test "export default predefined function", ->
};
export default foo;"""
- eq toJS(input), output
test "export default class", ->
- input = """
+ eqJS """
export default class foo extends bar
baz: ->
- console.log 'hello, world!'"""
- output = """
+ console.log 'hello, world!'""",
+ """
var foo;
export default foo = class foo extends bar {
@@ -463,42 +423,39 @@ test "export default class", ->
}
};"""
- eq toJS(input), output
test "export class", ->
- input = """
+ eqJS """
export class foo
baz: ->
- console.log 'hello, world!'"""
- output = """
+ console.log 'hello, world!'""",
+ """
export var foo = class foo {
baz() {
return console.log('hello, world!');
}
};"""
- eq toJS(input), output
test "export class that extends", ->
- input = """
+ eqJS """
export class foo extends bar
baz: ->
- console.log 'hello, world!'"""
- output = """
+ console.log 'hello, world!'""",
+ """
export var foo = class foo extends bar {
baz() {
return console.log('hello, world!');
}
};"""
- eq toJS(input), output
test "export default class that extends", ->
- input = """
+ eqJS """
export default class foo extends bar
baz: ->
- console.log 'hello, world!'"""
- output = """
+ console.log 'hello, world!'""",
+ """
var foo;
export default foo = class foo extends bar {
@@ -507,85 +464,77 @@ test "export default class that extends", ->
}
};"""
- eq toJS(input), output
test "export default named member, within an object", ->
- input = "export { foo as default, bar }"
- output = """
+ eqJS "export { foo as default, bar }",
+ """
export {
foo as default,
bar
};"""
- eq toJS(input), output
# Import and export in the same statement
test "export an entire module's contents", ->
- input = "export * from 'lib'"
- output = "export * from 'lib';"
- eq toJS(input), output
+ eqJS "export * from 'lib'",
+ "export * from 'lib';"
test "export members imported from another module", ->
- input = "export { foo, bar } from 'lib'"
- output = """
+ eqJS "export { foo, bar } from 'lib'",
+ """
export {
foo,
bar
} from 'lib';"""
- eq toJS(input), output
test "export as aliases members imported from another module", ->
- input = "export { foo as bar, baz as qux } from 'lib'"
- output = """
+ eqJS "export { foo as bar, baz as qux } from 'lib'",
+ """
export {
foo as bar,
baz as qux
} from 'lib';"""
- eq toJS(input), output
test "export list can contain CoffeeScript keywords", ->
- input = "export { unless } from 'lib'"
- output = """
+ eqJS "export { unless } from 'lib'",
+ """
export {
unless
} from 'lib';"""
- eq toJS(input), output
test "export list can contain CoffeeScript keywords when aliasing", ->
- input = "export { when as bar, baz as unless } from 'lib'"
- output = """
+ eqJS "export { when as bar, baz as unless } from 'lib'",
+ """
export {
when as bar,
baz as unless
} from 'lib';"""
- eq toJS(input), output
# Edge cases
test "multiline import with comments", ->
- input = """
+ eqJS """
import {
foo, # Not as good as bar
bar as baz # I prefer qux
- } from 'lib'"""
- output = """
+ } from 'lib'""",
+ """
import {
foo,
bar as baz
} from 'lib';"""
- eq toJS(input), output
test "`from` not part of an import or export statement can still be assigned", ->
from = 5
eq 5, from
test "a variable named `from` can be assigned after an import", ->
- input = """
+ eqJS """
import { foo } from 'lib'
- from = 5"""
- output = """
+ from = 5""",
+ """
var from;
import {
@@ -593,15 +542,14 @@ test "a variable named `from` can be assigned after an import", ->
} from 'lib';
from = 5;"""
- eq toJS(input), output
test "`from` can be assigned after a multiline import", ->
- input = """
+ eqJS """
import {
foo
} from 'lib'
- from = 5"""
- output = """
+ from = 5""",
+ """
var from;
import {
@@ -609,91 +557,81 @@ test "`from` can be assigned after a multiline import", ->
} from 'lib';
from = 5;"""
- eq toJS(input), output
test "`from` can be imported as a member name", ->
- input = "import { from } from 'lib'"
- output = """
+ eqJS "import { from } from 'lib'",
+ """
import {
from
} from 'lib';"""
- eq toJS(input), output
test "`from` can be imported as a member name and aliased", ->
- input = "import { from as foo } from 'lib'"
- output = """
+ eqJS "import { from as foo } from 'lib'",
+ """
import {
from as foo
} from 'lib';"""
- eq toJS(input), output
test "`from` can be used as an alias name", ->
- input = "import { foo as from } from 'lib'"
- output = """
+ eqJS "import { foo as from } from 'lib'",
+ """
import {
foo as from
} from 'lib';"""
- eq toJS(input), output
test "`as` can be imported as a member name", ->
- input = "import { as } from 'lib'"
- output = """
+ eqJS "import { as } from 'lib'",
+ """
import {
as
} from 'lib';"""
- eq toJS(input), output
test "`as` can be imported as a member name and aliased", ->
- input = "import { as as foo } from 'lib'"
- output = """
+ eqJS "import { as as foo } from 'lib'",
+ """
import {
as as foo
} from 'lib';"""
- eq toJS(input), output
test "`as` can be used as an alias name", ->
- input = "import { foo as as } from 'lib'"
- output = """
+ eqJS "import { foo as as } from 'lib'",
+ """
import {
foo as as
} from 'lib';"""
- eq toJS(input), output
test "CoffeeScript keywords can be used as imported names in import lists", ->
- input = """
+ eqJS """
import { unless as bar } from 'lib'
- bar.barMethod()"""
- output = """
+ bar.barMethod()""",
+ """
import {
unless as bar
} from 'lib';
bar.barMethod();"""
- eq toJS(input), output
test "`*` can be used in an expression on the same line as an export keyword", ->
- input = "export foo = (x) -> x * x"
- output = """
+ eqJS "export foo = (x) -> x * x",
+ """
export var foo = function(x) {
return x * x;
};"""
- eq toJS(input), output
- input = "export default foo = (x) -> x * x"
- output = """
+ eqJS "export default foo = (x) -> x * x",
+ """
var foo;
export default foo = function(x) {
return x * x;
};"""
- eq toJS(input), output
test "`*` and `from` can be used in an export default expression", ->
- input = """
+ eqJS """
export default foo.extend
bar: ->
from = 5
- from = from * 3"""
- output = """
+ from = from * 3""",
+ """
export default foo.extend({
bar: function() {
var from;
@@ -701,95 +639,84 @@ test "`*` and `from` can be used in an export default expression", ->
return from = from * 3;
}
});"""
- eq toJS(input), output
test "wrapped members can be imported multiple times if aliased", ->
- input = "import { foo, foo as bar } from 'lib'"
- output = """
+ eqJS "import { foo, foo as bar } from 'lib'",
+ """
import {
foo,
foo as bar
} from 'lib';"""
- eq toJS(input), output
test "default and wrapped members can be imported multiple times if aliased", ->
- input = "import foo, { foo as bar } from 'lib'"
- output = """
+ eqJS "import foo, { foo as bar } from 'lib'",
+ """
import foo, {
foo as bar
} from 'lib';"""
- eq toJS(input), output
test "import a member named default", ->
- input = "import { default } from 'lib'"
- output = """
+ eqJS "import { default } from 'lib'",
+ """
import {
default
} from 'lib';"""
- eq toJS(input), output
test "import an aliased member named default", ->
- input = "import { default as def } from 'lib'"
- output = """
+ eqJS "import { default as def } from 'lib'",
+ """
import {
default as def
} from 'lib';"""
- eq toJS(input), output
test "export a member named default", ->
- input = "export { default }"
- output = """
+ eqJS "export { default }",
+ """
export {
default
};"""
- eq toJS(input), output
test "export an aliased member named default", ->
- input = "export { def as default }"
- output = """
+ eqJS "export { def as default }",
+ """
export {
def as default
};"""
- eq toJS(input), output
test "import an imported member named default", ->
- input = "import { default } from 'lib'"
- output = """
+ eqJS "import { default } from 'lib'",
+ """
import {
default
} from 'lib';"""
- eq toJS(input), output
test "import an imported aliased member named default", ->
- input = "import { default as def } from 'lib'"
- output = """
+ eqJS "import { default as def } from 'lib'",
+ """
import {
default as def
} from 'lib';"""
- eq toJS(input), output
test "export an imported member named default", ->
- input = "export { default } from 'lib'"
- output = """
+ eqJS "export { default } from 'lib'",
+ """
export {
default
} from 'lib';"""
- eq toJS(input), output
test "export an imported aliased member named default", ->
- input = "export { default as def } from 'lib'"
- output = """
+ eqJS "export { default as def } from 'lib'",
+ """
export {
default as def
} from 'lib';"""
- eq toJS(input), output
test "#4394: export shouldn't prevent variable declarations", ->
- input = """
+ eqJS """
x = 1
export { x }
+ """,
"""
- output = """
var x;
x = 1;
@@ -798,19 +725,17 @@ test "#4394: export shouldn't prevent variable declarations", ->
x
};
"""
- eq toJS(input), output
test "#4451: `default` in an export statement is only treated as a keyword when it follows `export` or `as`", ->
- input = "export default { default: 1 }"
- output = """
+ eqJS "export default { default: 1 }",
+ """
export default {
default: 1
};
"""
- eq toJS(input), output
test "#4491: import- and export-specific lexing should stop after import/export statement", ->
- input = """
+ eqJS """
import {
foo,
bar as baz
@@ -819,8 +744,8 @@ test "#4491: import- and export-specific lexing should stop after import/export
foo as
3 * as 4
from 'foo'
- """
- output = """
+ """,
+ """
import {
foo,
bar as baz
@@ -832,16 +757,15 @@ test "#4491: import- and export-specific lexing should stop after import/export
from('foo');
"""
- eq toJS(input), output
- input = """
+ eqJS """
import { foo, bar as baz } from 'lib'
foo as
3 * as 4
from 'foo'
- """
- output = """
+ """,
+ """
import {
foo,
bar as baz
@@ -853,16 +777,15 @@ test "#4491: import- and export-specific lexing should stop after import/export
from('foo');
"""
- eq toJS(input), output
- input = """
+ eqJS """
import * as lib from 'lib'
foo as
3 * as 4
from 'foo'
- """
- output = """
+ """,
+ """
import * as lib from 'lib';
foo(as);
@@ -871,9 +794,8 @@ test "#4491: import- and export-specific lexing should stop after import/export
from('foo');
"""
- eq toJS(input), output
- input = """
+ eqJS """
export {
foo,
bar
@@ -882,8 +804,8 @@ test "#4491: import- and export-specific lexing should stop after import/export
foo as
3 * as 4
from 'foo'
- """
- output = """
+ """,
+ """
export {
foo,
bar
@@ -895,16 +817,15 @@ test "#4491: import- and export-specific lexing should stop after import/export
from('foo');
"""
- eq toJS(input), output
- input = """
+ eqJS """
export * from 'lib'
foo as
3 * as 4
from 'foo'
- """
- output = """
+ """,
+ """
export * from 'lib';
foo(as);
@@ -913,4 +834,3 @@ test "#4491: import- and export-specific lexing should stop after import/export
from('foo');
"""
- eq toJS(input), output
diff --git a/test/regexps.coffee b/test/regexps.coffee
index 8ee2b74c99..d5431de721 100644
--- a/test/regexps.coffee
+++ b/test/regexps.coffee
@@ -300,18 +300,16 @@ test "#4248: Unicode code point escapes", ->
ok /a\u{12345}c/.test 'a\ud808\udf45c'
# rewrite code point escapes unless u flag is set
- input = """
+ eqJS """
/\\u{bcdef}\\u{abc}/u
- """
- output = """
+ """,
+ """
/\\u{bcdef}\\u{abc}/u;
"""
- eq toJS(input), output
- input = """
+ eqJS """
///#{ 'a' }\\u{bcdef}///
- """
- output = """
+ """,
+ """
/a\\udab3\\uddef/;
"""
- eq toJS(input), output
diff --git a/test/strings.coffee b/test/strings.coffee
index 3e0407ecf9..54d6e85b22 100644
--- a/test/strings.coffee
+++ b/test/strings.coffee
@@ -415,18 +415,16 @@ test "#4248: Unicode code point escapes", ->
eq '\\u{123456}', "#{'\\'}#{'u{123456}'}"
# don't rewrite code point escapes
- input = """
+ eqJS """
'\\u{bcdef}\\u{abc}'
- """
- output = """
+ """,
+ """
'\\u{bcdef}\\u{abc}';
"""
- eq toJS(input), output
- input = """
+ eqJS """
"#{ 'a' }\\u{bcdef}"
- """
- output = """
+ """,
+ """
"a\\u{bcdef}";
"""
- eq toJS(input), output
diff --git a/test/support/helpers.coffee b/test/support/helpers.coffee
index 5ec9684156..a7cbbc1df0 100644
--- a/test/support/helpers.coffee
+++ b/test/support/helpers.coffee
@@ -1,4 +1,4 @@
-# See http://wiki.ecmascript.org/doku.php?id=harmony:egal
+# See [http://wiki.ecmascript.org/doku.php?id=harmony:egal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
egal = (a, b) ->
if a is b
a isnt 0 or 1/a is 1/b
@@ -13,9 +13,20 @@ arrayEgal = (a, b) ->
return no for el, idx in a when not arrayEgal el, b[idx]
yes
-exports.eq = (a, b, msg) -> ok egal(a, b), msg or "Expected #{a} to equal #{b}"
-exports.arrayEq = (a, b, msg) -> ok arrayEgal(a,b), msg or "Expected #{a} to deep equal #{b}"
+exports.eq = (a, b, msg) ->
+ ok egal(a, b), msg or
+ "Expected #{reset}#{a}#{red} to equal #{reset}#{b}#{red}"
-exports.toJS = (str) ->
- CoffeeScript.compile str, bare: yes
- .replace /^\s+|\s+$/g, '' # Trim leading/trailing whitespace
+exports.arrayEq = (a, b, msg) ->
+ ok arrayEgal(a,b), msg or
+ "Expected #{reset}#{a}#{red} to deep equal #{reset}#{b}#{red}"
+
+exports.eqJS = (input, expectedOutput, msg) ->
+ actualOutput = CoffeeScript.compile input, bare: yes
+ .replace /^\s+|\s+$/g, '' # Trim leading/trailing whitespace.
+
+ ok egal(expectedOutput, actualOutput), msg or
+ """Expected generated JavaScript to be:
+ #{reset}#{expectedOutput}#{red}
+ but instead it was:
+ #{reset}#{actualOutput}#{red}"""