Index: test/facade_converter_test.ts |
diff --git a/test/facade_converter_test.ts b/test/facade_converter_test.ts |
index e779fead7090611588a49252103b70ff07abfc45..ad635fdd8f90ff595abe6d8a3a8272e57b4cc4d1 100644 |
--- a/test/facade_converter_test.ts |
+++ b/test/facade_converter_test.ts |
@@ -1,7 +1,7 @@ |
/// <reference path="../typings/mocha/mocha.d.ts"/> |
import * as fs from 'fs'; |
-import {expectTranslate, FAKE_MAIN, translateSource} from './test_support'; |
-import chai = require('chai'); |
+ |
+import {expectTranslate, FAKE_MAIN} from './test_support'; |
let es6RuntimeDeclarations = ` |
interface Iterable<T> {} |
@@ -28,20 +28,8 @@ let es6RuntimeDeclarations = ` |
function getSources(str: string): {[k: string]: string} { |
let srcs: {[k: string]: string} = { |
'some/path/to/typings/es6-shim/es6-shim': es6RuntimeDeclarations, |
- 'angular2/src/core/di/forward_ref.d.ts': ` |
- export declare function forwardRef<T>(x: T): T;`, |
'some/path/to/typings/es6-promise/es6-promise.d.ts': |
fs.readFileSync('typings/es6-promise/es6-promise.d.ts', 'utf-8'), |
- 'node_modules/rxjs/Observable.d.ts': ` |
- export declare class Observable {}`, |
- 'angular2/src/facade/async.ts': ` |
- export {Observable} from 'rxjs/Observable';`, |
- 'angular2/src/facade/collection.ts': ` |
- export declare var Map;`, |
- 'angular2/src/facade/lang.d.ts': ` |
- interface List<T> extends Array<T> {} |
- export declare function CONST_EXPR<T>(x: T): T; |
- export declare var normalizeBlank: (x: Object) => any;`, |
'other/file.ts': ` |
export class X { |
map(x: number): string { return String(x); } |
@@ -64,399 +52,76 @@ function expectWithTypes(str: string) { |
return expectTranslate(getSources(str), COMPILE_OPTS); |
} |
-function expectErroneousWithType(str: string) { |
- return chai.expect(() => translateSource(getSources(str), COMPILE_OPTS)); |
-} |
- |
describe('type based translation', () => { |
describe('Dart type substitution', () => { |
it('finds registered substitutions', () => { |
- expectWithTypes( |
- 'import {Observable} from "angular2/src/facade/async"; var o: Observable<Date>;') |
- .to.equal(`import "package:angular2/src/facade/async.dart" show Stream; |
+ expectWithTypes('const n: Node;').to.equal(`import "dart:html"; |
-Stream<DateTime> o;`); |
- expectWithTypes('var p: Promise<void> = x;').to.equal(`import "dart:async"; |
+@JS() |
+external Node get n;`); |
+ expectWithTypes('const xhr: XMLHttpRequest;').to.equal(`import "dart:html"; |
-Future p = x;`); |
- expectWithTypes('var y: Promise;').to.equal(`import "dart:async"; |
+@JS() |
+external HttpRequest get xhr;`); |
+ expectWithTypes('const intArray: Uint8Array;').to.equal(`import "dart:typed_data"; |
-Future y;`); |
- expectWithTypes('var n: Node;').to.equal('dynamic n;'); |
- expectWithTypes('var xhr: XMLHttpRequest;').to.equal(`import "dart:html"; |
+@JS() |
+external Uint8List get intArray;`); |
+ expectWithTypes('const buff: ArrayBuffer;').to.equal(`import "dart:typed_data"; |
-HttpRequest xhr;`); |
- expectWithTypes('var intArray: Uint8Array;').to.equal(`import "dart:typed_arrays"; |
- |
-Uint8List intArray;`); |
- expectWithTypes('var buff: ArrayBuffer;').to.equal(`import "dart:typed_arrays"; |
- |
-ByteBuffer buff;`); |
+@JS() |
+external ByteBuffer get buff;`); |
}); |
- it('allows undeclared types', () => { expectWithTypes('var t: Thing;').to.equal('Thing t;'); }); |
- |
- it('does not substitute matching name from different file', () => { |
- expectWithTypes('import {Promise} from "other/file"; var y = x instanceof Promise;') |
- .to.equal(`import "package:other/file.dart" show Promise; |
- |
-var y = x is Promise;`); |
+ it('allows undeclared types', () => { |
+ expectWithTypes('const t: Thing;').to.equal(`@JS() |
+external Thing get t;`); |
}); |
- |
- it('does not substitute all identifiers', |
- () => { expectWithTypes('let Promise = 1;').to.equal(`var Promise = 1;`); }); |
}); |
- describe('collection façade', () => { |
- it('translates array operations to dartisms', () => { |
- expectWithTypes('function f() { var x: Array<number> = []; x.push(1); x.pop(); }') |
- .to.equal(`f() { |
- List<num> x = []; |
- x.add(1); |
- x.removeLast(); |
-}`); |
- expectWithTypes('function f() { var x: Array<number> = []; x.map((e) => e); }') |
- .to.equal(`f() { |
- List<num> x = []; |
- x.map((e) => e).toList(); |
-}`); |
- expectWithTypes('function f() { var x: Array<number> = []; x.filter((e) => true); }') |
- .to.equal(`f() { |
- List<num> x = []; |
- x.where((e) => true).toList(); |
-}`); |
- expectWithTypes('function f() { var x: Array<number> = []; x.unshift(1, 2, 3); x.shift(); }') |
- .to.equal(`f() { |
- List<num> x = []; |
- (x..insertAll(0, [1, 2, 3])).length; |
- x.removeAt(0); |
-}`); |
- expectWithTypes('function f() { var x: Array<number> = []; x.unshift(1); }').to.equal(`f() { |
- List<num> x = []; |
- (x..insert(0, 1)).length; |
-}`); |
- expectWithTypes('function f() { var x: Array<number> = []; x.concat([1], x).length; }') |
- .to.equal(`f() { |
- List<num> x = []; |
- (new List.from(x)..addAll([1])..addAll(x)).length; |
-}`); |
- expectWithTypes('var x: Array<number> = []; var y: Array<number> = x.slice(0);') |
- .to.equal(`List<num> x = []; |
-List<num> y = ListWrapper.slice(x, 0);`); |
- expectWithTypes('var x: Array<number> = []; var y: Array<number> = x.splice(0,1);') |
- .to.equal(`List<num> x = []; |
-List<num> y = ListWrapper.splice(x, 0, 1);`); |
- expectWithTypes('var x: Array<number> = []; var y: string = x.join("-");') |
- .to.equal(`List<num> x = []; |
-String y = x.join("-");`); |
- expectWithTypes('var x: Array<number> = []; var y: string = x.join();') |
- .to.equal(`List<num> x = []; |
-String y = x.join(",");`); |
- expectWithTypes('var x: Array<number> = []; var y: number = x.find((e) => e == 0);') |
- .to.equal(`List<num> x = []; |
-num y = x.firstWhere((e) => e == 0, orElse: () => null);`); |
- expectWithTypes('var x: Array<number> = []; var y: boolean = x.some((e) => e == 0);') |
- .to.equal(`List<num> x = []; |
-bool y = x.any((e) => e == 0);`); |
- expectWithTypes('var x: Array<number> = []; var y: number = x.reduce((a, b) => a + b, 0);') |
- .to.equal(`List<num> x = []; |
-num y = x.fold(0, (a, b) => a + b);`); |
- expectWithTypes('var x: Array<number> = []; var y: number = x.reduce((a, b) => a + b);') |
- .to.equal(`List<num> x = []; |
-num y = x.fold(null, (a, b) => a + b);`); |
- }); |
- |
- it('translates console.log', () => { |
- expectWithTypes(`console.log(1);`).to.equal('print(1);'); |
- expectWithTypes(`console.log(1, 2);`).to.equal('print([1, 2].join(" "));'); |
+ describe('skip top level calls', () => { |
+ it('console.log', () => { |
+ expectWithTypes(`console.log(1);`).to.equal(''); |
+ expectWithTypes(`console.log(1, 2);`).to.equal(''); |
}); |
- |
- it('translates string methoids', |
- () => { expectErroneousWithType(`var x = 'asd'.substr(0, 1);`).to.throw(/use substring/); }); |
- |
- it('translates map operations to dartisms', () => { |
- expectWithTypes('function f() { var x = new Map<string, string>(); x.set("k", "v"); }') |
- .to.equal(`f() { |
- var x = new Map<String, String>(); |
- x["k"] = "v"; |
-}`); |
- expectWithTypes('function f() { var x = new Map<string, string>(); x.get("k"); }') |
- .to.equal(`f() { |
- var x = new Map<String, String>(); |
- x["k"]; |
-}`); |
- expectWithTypes('function f() { var x = new Map<string, string>(); x.has("k"); }') |
- .to.equal(`f() { |
- var x = new Map<String, String>(); |
- x.containsKey("k"); |
-}`); |
- expectWithTypes('function f() { var x = new Map<string, string>(); x.delete("k"); }') |
- .to.equal(`f() { |
- var x = new Map<String, String>(); |
- (x.containsKey("k") && (x.remove("k") != null || true)); |
-}`); |
- expectWithTypes( |
- 'function f() { var x = new Map<string, string>(); x.forEach((v, k) => null); }') |
- .to.equal(`f() { |
- var x = new Map<String, String>(); |
- x.forEach((k, v) => null); |
-}`); |
- expectWithTypes( |
- 'function f() { var x = new Map<string, string>(); x.forEach(function (v, k) { return null; }); }') |
- .to.equal(`f() { |
- var x = new Map<String, String>(); |
- x.forEach((k, v) { |
- return null; |
- }); |
-}`); |
- expectWithTypes( |
- 'function f() { var x = new Map<string, string>(); var y = x.forEach((v, k) => { return null; }); }') |
- .to.equal(`f() { |
- var x = new Map<String, String>(); |
- var y = x.forEach((k, v) { |
- return null; |
- }); |
-}`); |
- |
- expectWithTypes('function f() { var x = new Map<string, string>(); x.forEach(fn); }') |
- .to.equal(`f() { |
- var x = new Map<String, String>(); |
- x.forEach((k, v) => (fn)(v, k)); |
-}`); |
- }); |
- |
- it('translates map properties to dartisms', () => { |
- expectWithTypes('var x = new Map<string, string>();var y = x.size;') |
- .to.equal(`var x = new Map<String, String>(); |
-var y = x.length;`); |
- }); |
- }); |
- |
- describe('regexp', () => { |
- expectWithTypes('function f() { var x = /a/g; x.test("a"); }').to.equal(`f() { |
- var x = new RegExp(r'a'); |
- x.hasMatch("a"); |
-}`); |
- expectWithTypes('function f() { var result = /a(.)/g.exec("ab")[1]; }').to.equal(`f() { |
- var result = new RegExp(r'a(.)').firstMatch("ab")[1]; |
-}`); |
- expectWithTypes('function f() { let groups = /a(.)/g.exec("ab"); }').to.equal(`f() { |
- var groups = ((match) => new List.generate( |
- 1 + match.groupCount, match.group))(new RegExp(r'a(.)').firstMatch("ab")); |
-}`); |
- expectErroneousWithType('function f() { var x = /a(.)/g; x.exec("ab")[1]; }') |
- .to.throw( |
- 'exec is only supported on regexp literals, ' + |
- 'to avoid side-effect of multiple calls on global regexps.'); |
- }); |
- |
- describe('promises', () => { |
- it('translates into Futures', () => { |
- expectWithTypes('let x: Promise = Promise.resolve(1);').to.equal(`import "dart:async"; |
- |
-Future x = Future.value(1);`); |
- expectWithTypes('let x: Promise = Promise.reject(1);').to.equal(`import "dart:async"; |
- |
-Future x = Future.error(1);`); |
- expectWithTypes('let x: Promise = new Promise((resolve) => {resolve(1);});') |
- .to.equal(`import "dart:async"; |
- |
-Future x = (() { |
- Completer _completer$$ts2dart$0 = new Completer(); |
- var resolve = _completer$$ts2dart$0.complete; |
- (() { |
- resolve(1); |
- })(); |
- return _completer$$ts2dart$0.future; |
-})();`); |
- expectWithTypes('let x: Promise = new Promise((resolve, reject) => {resolve(1);});') |
- .to.equal(`import "dart:async"; |
- |
-Future x = (() { |
- Completer _completer$$ts2dart$0 = new Completer(); |
- var resolve = _completer$$ts2dart$0.complete; |
- var reject = _completer$$ts2dart$0.completeError; |
- (() { |
- resolve(1); |
- })(); |
- return _completer$$ts2dart$0.future; |
-})();`); |
- expectWithTypes('let x: Promise = new Promise((myParam1, myParam2) => {myParam1(1);});') |
- .to.equal(`import "dart:async"; |
- |
-Future x = (() { |
- Completer _completer$$ts2dart$0 = new Completer(); |
- var myParam1 = _completer$$ts2dart$0.complete; |
- var myParam2 = _completer$$ts2dart$0.completeError; |
- (() { |
- myParam1(1); |
- })(); |
- return _completer$$ts2dart$0.future; |
-})();`); |
- expectWithTypes( |
- 'let x: Promise<any> = new Promise((resolve, reject) => {resolve(1);});' + |
- 'function fn(): void { x.then((v) => { console.log(v) }).catch((err) => { console.log(err); }); }') |
- .to.equal(`import "dart:async"; |
- |
-Future<dynamic> x = (() { |
- Completer _completer$$ts2dart$0 = new Completer(); |
- var resolve = _completer$$ts2dart$0.complete; |
- var reject = _completer$$ts2dart$0.completeError; |
- (() { |
- resolve(1); |
- })(); |
- return _completer$$ts2dart$0.future; |
-})(); |
-void fn() { |
- x.then((v) { |
- print(v); |
- }).catchError((err) { |
- print(err); |
}); |
-}`); |
- expectWithTypes( |
- 'var fn: () => Promise<number>;' + |
- 'function main() { fn().then((v) => { console.log(v) }).catch((err) => { console.log(err); }); }') |
- .to.equal(`import "dart:async"; |
-dynamic /* () => Promise<number> */ fn; |
-main() { |
- fn().then((v) { |
- print(v); |
- }).catchError((err) { |
- print(err); |
- }); |
-}`); |
+ describe('const', () => { |
+ it('simple', () => { |
+ expectWithTypes('const x = 1;').to.equal(`@JS() |
+external get x;`); |
+ expectWithTypes('const x = [];').to.equal(`@JS() |
+external get x;`); |
expectWithTypes( |
- 'var fn: () => Promise<number>;' + |
- 'function main() { fn().then((v) => { console.log(v) }, (err) => { console.log(err); }); }') |
- .to.equal(`import "dart:async"; |
+ 'class Person {}' + |
+ 'const x = new Person();') |
+ .to.equal(`@JS() |
+class Person { |
+ // @Ignore |
+ Person.fakeConstructor$(); |
+} |
-dynamic /* () => Promise<number> */ fn; |
-main() { |
- fn().then((v) { |
- print(v); |
- }).catchError((err) { |
- print(err); |
- }); |
-}`); |
+@JS() |
+external get x;`); |
}); |
}); |
- describe( |
- 'builtin functions', () => { |
- it('translates CONST_EXPR(...) to const (...)', () => { |
- expectWithTypes( |
- 'import {CONST_EXPR} from "angular2/src/facade/lang";\n' + |
- 'const x = CONST_EXPR(1);') |
- .to.equal('const x = 1;'); |
- expectWithTypes( |
- 'import {CONST_EXPR} from "angular2/src/facade/lang";\n' + |
- 'const x = CONST_EXPR([]);') |
- .to.equal('const x = const [];'); |
- expectWithTypes( |
- 'import {CONST_EXPR} from "angular2/src/facade/lang";\n' + |
- 'class Person {}' + |
- 'const x = CONST_EXPR(new Person());') |
- .to.equal(`class Person {} |
- |
-const x = const Person();`); |
- expectWithTypes( |
- 'import {CONST_EXPR} from "angular2/src/facade/lang";\n' + |
- 'const x = CONST_EXPR({"one":1});') |
- .to.equal('const x = const {"one": 1};'); |
- expectWithTypes( |
- 'import {CONST_EXPR} from "angular2/src/facade/lang";\n' + |
- 'import {Map} from "angular2/src/facade/collection";\n' + |
- 'const x = CONST_EXPR(new Map());') |
- .to.equal(`import "package:angular2/src/facade/collection.dart" show Map; |
- |
-const x = const {};`); |
- expectWithTypes( |
- 'import {CONST_EXPR} from "angular2/src/facade/lang";\n' + |
- 'import {Map} from "angular2/src/facade/collection";\n' + |
- 'const x = CONST_EXPR(new Map<number, string>());') |
- .to.equal(`import "package:angular2/src/facade/collection.dart" show Map; |
- |
-const x = const <num, String>{};`); |
- |
- expectWithTypes(` |
- import {CONST_EXPR} from "angular2/src/facade/lang"; |
- const _EMPTY_LIST = CONST_EXPR([]);`) |
- .to.equal(`const _EMPTY_LIST = const [];`); |
- expectWithTypes(` |
- import {CONST_EXPR} from "angular2/src/facade/lang"; |
- const _EMPTY_LIST = CONST_EXPR(<string[]>[]);`) |
- .to.equal(`const _EMPTY_LIST = const <String>[];`); |
- expectWithTypes(` |
- import {CONST_EXPR} from "angular2/src/facade/lang"; |
- const MY_MAP = CONST_EXPR(<{[k: string]: number}>{});`) |
- .to.equal(`const MY_MAP = const <String, num>{};`); |
- }); |
- |
- it('translates forwardRef(() => T) to T', |
- () => { |
- expectWithTypes( |
- 'import {forwardRef} from "angular2/src/core/di/forward_ref";\n' + |
- 'var SomeType = 1;\n' + |
- 'var x = forwardRef(() => SomeType);') |
- .to.equal(`var SomeType = 1; |
-var x = SomeType;`); |
- expectErroneousWithType(`import {forwardRef} from "angular2/src/core/di/forward_ref"; |
-forwardRef(1)`).to.throw(/only arrow functions/); |
- }); |
- |
- it('erases calls to normalizeBlank', () => { |
- expectWithTypes( |
- 'import {normalizeBlank} from "angular2/src/facade/lang";\n' + |
- 'var x = normalizeBlank([]);') |
- .to.equal('var x = [];'); |
- }); |
- }); |
- |
it('translates array façades', () => { |
- expectWithTypes('function f() { var x = []; Array.isArray(x); }').to.equal(`f() { |
- var x = []; |
- ((x) is List); |
-}`); |
+ expectWithTypes('function f() : string[] {}').to.equal(`@JS() |
+external List<String> f();`); |
}); |
describe('error detection', () => { |
- describe('Map', () => { |
- it('.forEach() should report an error when the callback doesn\'t have 2 args', () => { |
- expectErroneousWithType('var x = new Map<string, string>(); x.forEach((v, k, m) => null);') |
- .to.throw('Map.forEach callback requires exactly two arguments'); |
- }); |
- }); |
- |
- describe('Array', () => { |
- it('.concat() should report an error if any arg is not an Array', () => { |
- expectErroneousWithType('var x: Array<number> = []; x.concat(1);') |
- .to.throw('Array.concat only takes Array arguments'); |
- }); |
- }); |
- |
- it('for untyped symbols matching special cased fns', () => { |
- expectErroneousWithType('forwardRef(1)').to.throw(/Untyped property access to "forwardRef"/); |
- }); |
- |
- it('for untyped symbols matching special cased methods', () => { |
- expectErroneousWithType('x.push(1)').to.throw(/Untyped property access to "push"/); |
- }); |
- |
- it('allows unrelated methods', () => { |
+ it('support imports', () => { |
expectWithTypes( |
'import {X} from "other/file";\n' + |
- 'var y = new X().map(1)') |
- .to.equal(`import "package:other/file.dart" show X; |
- |
-var y = new X().map(1);`); |
- expectWithTypes(`import {X} from "other/file"; |
-var y = X.get({"a": 1}, "a");`) |
+ 'let x:X;') |
.to.equal(`import "package:other/file.dart" show X; |
-var y = X.get({"a": 1}, "a");`); |
- expectWithTypes('["a", "b"].map((x) => x);').to.equal('["a", "b"].map((x) => x).toList();'); |
+@JS() |
+external X get x; |
+@JS() |
+external set x(X v);`); |
}); |
}); |
}); |