feat(transformers): directive aliases in Dart transformers (fix #1747)
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
library angular2.test.transform.common.annotation_matcher_test;
|
||||
|
||||
import 'package:angular2/src/render/api.dart';
|
||||
import 'package:angular2/src/transform/common/ng_meta.dart';
|
||||
import 'package:guinness/guinness.dart';
|
||||
|
||||
main() => allTests();
|
||||
|
||||
void allTests() {
|
||||
var mockData = [
|
||||
new DirectiveMetadata(id: 'm1'),
|
||||
new DirectiveMetadata(id: 'm2'),
|
||||
new DirectiveMetadata(id: 'm3'),
|
||||
new DirectiveMetadata(id: 'm4')
|
||||
];
|
||||
|
||||
it('should allow empty data.', () {
|
||||
var ngMeta = new NgMeta.empty();
|
||||
expect(ngMeta.isEmpty).toBeTrue();
|
||||
});
|
||||
|
||||
describe('serialization', () {
|
||||
it('should parse empty data correctly.', () {
|
||||
var ngMeta = new NgMeta.fromJson({});
|
||||
expect(ngMeta.isEmpty).toBeTrue();
|
||||
});
|
||||
|
||||
it('should be lossless', () {
|
||||
var a = new NgMeta.empty();
|
||||
a.types['T0'] = mockData[0];
|
||||
a.types['T1'] = mockData[1];
|
||||
a.types['T2'] = mockData[2];
|
||||
a.types['T3'] = mockData[3];
|
||||
a.aliases['a1'] = ['T1'];
|
||||
a.aliases['a2'] = ['a1'];
|
||||
a.aliases['a3'] = ['T3', 'a2'];
|
||||
a.aliases['a4'] = ['a3', 'T3'];
|
||||
_checkSimilar(a, new NgMeta.fromJson(a.toJson()));
|
||||
});
|
||||
});
|
||||
|
||||
describe('flatten', () {
|
||||
it('should include recursive aliases.', () {
|
||||
var a = new NgMeta.empty();
|
||||
a.types['T0'] = mockData[0];
|
||||
a.types['T1'] = mockData[1];
|
||||
a.types['T2'] = mockData[2];
|
||||
a.types['T3'] = mockData[3];
|
||||
a.aliases['a1'] = ['T1'];
|
||||
a.aliases['a2'] = ['a1'];
|
||||
a.aliases['a3'] = ['T3', 'a2'];
|
||||
a.aliases['a4'] = ['a3', 'T0'];
|
||||
expect(a.flatten('a4')).toEqual([mockData[3], mockData[1], mockData[0]]);
|
||||
});
|
||||
|
||||
it('should detect cycles.', () {
|
||||
var a = new NgMeta.empty();
|
||||
a.types['T0'] = mockData[0];
|
||||
a.aliases['a1'] = ['T0', 'a1'];
|
||||
a.aliases['a2'] = ['a1'];
|
||||
expect(a.flatten('a1')).toEqual([mockData[0]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('merge', () {
|
||||
it('should merge all types on addAll', () {
|
||||
var a = new NgMeta.empty();
|
||||
var b = new NgMeta.empty();
|
||||
a.types['T0'] = mockData[0];
|
||||
b.types['T1'] = mockData[1];
|
||||
a.addAll(b);
|
||||
expect(a.types).toContain('T1');
|
||||
expect(a.types['T1']).toEqual(mockData[1]);
|
||||
});
|
||||
|
||||
it('should merge all aliases on addAll', () {
|
||||
var a = new NgMeta.empty();
|
||||
var b = new NgMeta.empty();
|
||||
a.aliases['a'] = ['x'];
|
||||
b.aliases['b'] = ['y'];
|
||||
a.addAll(b);
|
||||
expect(a.aliases).toContain('b');
|
||||
expect(a.aliases['b']).toEqual(['y']);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
_checkSimilar(NgMeta a, NgMeta b) {
|
||||
expect(a.types.length).toEqual(b.types.length);
|
||||
expect(a.aliases.length).toEqual(b.aliases.length);
|
||||
for (var k in a.types.keys) {
|
||||
expect(b.types).toContain(k);
|
||||
var at = a.types[k];
|
||||
var bt = b.types[k];
|
||||
expect(at.id).toEqual(bt.id);
|
||||
}
|
||||
for (var k in a.aliases.keys) {
|
||||
expect(b.aliases).toContain(k);
|
||||
expect(b.aliases[k]).toEqual(a.aliases[k]);
|
||||
}
|
||||
}
|
||||
@@ -37,9 +37,12 @@ void allTests() {
|
||||
});
|
||||
|
||||
it('should parse compile children values', () async {
|
||||
var ngDeps = await NgDeps.parse(reader, new AssetId('a',
|
||||
'directive_metadata_extractor/'
|
||||
'directive_metadata_files/compile_children.ng_deps.dart'));
|
||||
var ngDeps = await NgDeps.parse(
|
||||
reader,
|
||||
new AssetId(
|
||||
'a',
|
||||
'directive_metadata_extractor/'
|
||||
'directive_metadata_files/compile_children.ng_deps.dart'));
|
||||
var it = ngDeps.registeredTypes.iterator;
|
||||
|
||||
// Unset value defaults to `true`.
|
||||
@@ -122,71 +125,108 @@ void allTests() {
|
||||
|
||||
it('should fail when a class is annotated with multiple Directives.',
|
||||
() async {
|
||||
var ngDeps = await NgDeps.parse(reader, new AssetId('a',
|
||||
'directive_metadata_extractor/'
|
||||
'directive_metadata_files/too_many_directives.ng_deps.dart'));
|
||||
expect(() => ngDeps.registeredTypes.first.directiveMetadata).toThrowWith(
|
||||
anInstanceOf: PrintLoggerError);
|
||||
var ngDeps = await NgDeps.parse(
|
||||
reader,
|
||||
new AssetId(
|
||||
'a',
|
||||
'directive_metadata_extractor/'
|
||||
'directive_metadata_files/too_many_directives.ng_deps.dart'));
|
||||
expect(() => ngDeps.registeredTypes.first.directiveMetadata)
|
||||
.toThrowWith(anInstanceOf: PrintLoggerError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('extractMetadata', () {
|
||||
it('should generate `DirectiveMetadata` from .ng_deps.dart files.',
|
||||
() async {
|
||||
var extracted = await extractDirectiveMetadata(reader, new AssetId(
|
||||
'a', 'directive_metadata_extractor/simple_files/foo.ng_deps.dart'));
|
||||
expect(extracted).toContain('FooComponent');
|
||||
var extracted = await extractDirectiveMetadata(
|
||||
reader,
|
||||
new AssetId('a',
|
||||
'directive_metadata_extractor/simple_files/foo.ng_deps.dart'));
|
||||
expect(extracted.types).toContain('FooComponent');
|
||||
|
||||
var extractedMeta = extracted['FooComponent'];
|
||||
var extractedMeta = extracted.types['FooComponent'];
|
||||
expect(extractedMeta.selector).toEqual('[foo]');
|
||||
});
|
||||
|
||||
it('should generate `DirectiveMetadata` from .ng_deps.dart files that use '
|
||||
'automatic adjacent string concatenation.', () async {
|
||||
var extracted = await extractDirectiveMetadata(reader, new AssetId('a',
|
||||
'directive_metadata_extractor/adjacent_strings_files/'
|
||||
'foo.ng_deps.dart'));
|
||||
expect(extracted).toContain('FooComponent');
|
||||
it(
|
||||
'should generate `DirectiveMetadata` from .ng_deps.dart files that use '
|
||||
'automatic adjacent string concatenation.',
|
||||
() async {
|
||||
var extracted = await extractDirectiveMetadata(
|
||||
reader,
|
||||
new AssetId(
|
||||
'a',
|
||||
'directive_metadata_extractor/adjacent_strings_files/'
|
||||
'foo.ng_deps.dart'));
|
||||
expect(extracted.types).toContain('FooComponent');
|
||||
|
||||
var extractedMeta = extracted['FooComponent'];
|
||||
var extractedMeta = extracted.types['FooComponent'];
|
||||
expect(extractedMeta.selector).toEqual('[foo]');
|
||||
});
|
||||
|
||||
it('should include `DirectiveMetadata` from exported files.', () async {
|
||||
var extracted = await extractDirectiveMetadata(reader, new AssetId(
|
||||
'a', 'directive_metadata_extractor/export_files/foo.ng_deps.dart'));
|
||||
expect(extracted).toContain('FooComponent');
|
||||
expect(extracted).toContain('BarComponent');
|
||||
var extracted = await extractDirectiveMetadata(
|
||||
reader,
|
||||
new AssetId('a',
|
||||
'directive_metadata_extractor/export_files/foo.ng_deps.dart'));
|
||||
expect(extracted.types).toContain('FooComponent');
|
||||
expect(extracted.types).toContain('BarComponent');
|
||||
|
||||
expect(extracted['FooComponent'].selector).toEqual('[foo]');
|
||||
expect(extracted['BarComponent'].selector).toEqual('[bar]');
|
||||
expect(extracted.types['FooComponent'].selector).toEqual('[foo]');
|
||||
expect(extracted.types['BarComponent'].selector).toEqual('[bar]');
|
||||
});
|
||||
|
||||
it('should include `DirectiveMetadata` recursively from exported files.',
|
||||
() async {
|
||||
var extracted = await extractDirectiveMetadata(reader, new AssetId('a',
|
||||
'directive_metadata_extractor/recursive_export_files/foo.ng_deps.dart'));
|
||||
expect(extracted).toContain('FooComponent');
|
||||
expect(extracted).toContain('BarComponent');
|
||||
expect(extracted).toContain('BazComponent');
|
||||
var extracted = await extractDirectiveMetadata(
|
||||
reader,
|
||||
new AssetId('a',
|
||||
'directive_metadata_extractor/recursive_export_files/foo.ng_deps.dart'));
|
||||
expect(extracted.types).toContain('FooComponent');
|
||||
expect(extracted.types).toContain('BarComponent');
|
||||
expect(extracted.types).toContain('BazComponent');
|
||||
|
||||
expect(extracted['FooComponent'].selector).toEqual('[foo]');
|
||||
expect(extracted['BarComponent'].selector).toEqual('[bar]');
|
||||
expect(extracted['BazComponent'].selector).toEqual('[baz]');
|
||||
expect(extracted.types['FooComponent'].selector).toEqual('[foo]');
|
||||
expect(extracted.types['BarComponent'].selector).toEqual('[bar]');
|
||||
expect(extracted.types['BazComponent'].selector).toEqual('[baz]');
|
||||
});
|
||||
|
||||
it('should include `DirectiveMetadata` from exported files '
|
||||
'expressed as absolute uris', () async {
|
||||
reader.addAsset(new AssetId('bar', 'lib/bar.ng_deps.dart'), readFile(
|
||||
'directive_metadata_extractor/absolute_export_files/bar.ng_deps.dart'));
|
||||
it(
|
||||
'should include `DirectiveMetadata` from exported files '
|
||||
'expressed as absolute uris',
|
||||
() async {
|
||||
reader.addAsset(
|
||||
new AssetId('bar', 'lib/bar.ng_deps.dart'),
|
||||
readFile(
|
||||
'directive_metadata_extractor/absolute_export_files/bar.ng_deps.dart'));
|
||||
|
||||
var extracted = await extractDirectiveMetadata(reader, new AssetId('a',
|
||||
'directive_metadata_extractor/absolute_export_files/foo.ng_deps.dart'));
|
||||
expect(extracted).toContain('FooComponent');
|
||||
expect(extracted).toContain('BarComponent');
|
||||
var extracted = await extractDirectiveMetadata(
|
||||
reader,
|
||||
new AssetId('a',
|
||||
'directive_metadata_extractor/absolute_export_files/foo.ng_deps.dart'));
|
||||
expect(extracted.types).toContain('FooComponent');
|
||||
expect(extracted.types).toContain('BarComponent');
|
||||
|
||||
expect(extracted['FooComponent'].selector).toEqual('[foo]');
|
||||
expect(extracted['BarComponent'].selector).toEqual('[bar]');
|
||||
expect(extracted.types['FooComponent'].selector).toEqual('[foo]');
|
||||
expect(extracted.types['BarComponent'].selector).toEqual('[bar]');
|
||||
});
|
||||
|
||||
it('should include directive aliases', () async {
|
||||
reader.addAsset(
|
||||
new AssetId('bar', 'lib/bar.ng_deps.dart'),
|
||||
readFile(
|
||||
'directive_metadata_extractor/directive_aliases_files/bar.ng_deps.dart'));
|
||||
|
||||
var extracted = await extractDirectiveMetadata(
|
||||
reader,
|
||||
new AssetId('a',
|
||||
'directive_metadata_extractor/directive_aliases_files/foo.ng_deps.dart'));
|
||||
expect(extracted.aliases).toContain('alias1');
|
||||
expect(extracted.aliases).toContain('alias2');
|
||||
expect(extracted.aliases['alias1']).toContain('BarComponent');
|
||||
expect(extracted.aliases['alias2']).toContain('FooComponent');
|
||||
expect(extracted.aliases['alias2']).toContain('alias1');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"alias1": {
|
||||
"kind": "alias",
|
||||
"value": [
|
||||
"BarComponent"
|
||||
]
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
library foo.ng_deps.dart;
|
||||
|
||||
import 'bar.dart';
|
||||
import 'package:angular2/src/core/annotations/annotations.dart';
|
||||
|
||||
var _visited = false;
|
||||
void initReflector(reflector) {
|
||||
if (_visited) return;
|
||||
_visited = true;
|
||||
reflector
|
||||
..registerType(BarComponent, {
|
||||
'factory': () => new BarComponent(),
|
||||
'parameters': const [],
|
||||
'annotations': const [const Component(selector: '[bar]')]
|
||||
});
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"alias2": {
|
||||
"kind": "alias",
|
||||
"value": [
|
||||
"FooComponent",
|
||||
"alias1"
|
||||
]
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
library foo.ng_deps.dart;
|
||||
|
||||
import 'foo.dart';
|
||||
import 'package:angular2/src/core/annotations/annotations.dart';
|
||||
|
||||
export 'bar.dart';
|
||||
import 'bar.ng_deps.dart' as i0;
|
||||
|
||||
var _visited = false;
|
||||
void initReflector(reflector) {
|
||||
if (_visited) return;
|
||||
_visited = true;
|
||||
reflector
|
||||
..registerType(FooComponent, {
|
||||
'factory': () => new FooComponent(),
|
||||
'parameters': const [],
|
||||
'annotations': const [const Component(selector: '[foo]')]
|
||||
});
|
||||
i0.initReflector(reflector);
|
||||
}
|
||||
@@ -1,10 +1,13 @@
|
||||
library angular2.test.transform.directive_processor.all_tests;
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:barback/barback.dart';
|
||||
import 'package:angular2/src/transform/directive_processor/rewriter.dart';
|
||||
import 'package:angular2/src/transform/common/annotation_matcher.dart';
|
||||
import 'package:angular2/src/transform/common/asset_reader.dart';
|
||||
import 'package:angular2/src/transform/common/logging.dart' as log;
|
||||
import 'package:angular2/src/transform/common/ng_meta.dart';
|
||||
import 'package:code_transformers/messages/build_logger.dart';
|
||||
import 'package:dart_style/dart_style.dart';
|
||||
import 'package:guinness/guinness.dart';
|
||||
@@ -18,45 +21,50 @@ main() {
|
||||
}
|
||||
|
||||
void allTests() {
|
||||
_testNgDeps('should preserve parameter annotations as const instances.',
|
||||
_testProcessor('should preserve parameter annotations as const instances.',
|
||||
'parameter_metadata/soup.dart');
|
||||
|
||||
_testNgDeps('should recognize custom annotations with package: imports',
|
||||
_testProcessor('should recognize custom annotations with package: imports',
|
||||
'custom_metadata/package_soup.dart',
|
||||
customDescriptors: [
|
||||
const ClassDescriptor('Soup', 'package:soup/soup.dart',
|
||||
superClass: 'Component'),
|
||||
]);
|
||||
|
||||
_testNgDeps('should recognize custom annotations with relative imports',
|
||||
_testProcessor('should recognize custom annotations with relative imports',
|
||||
'custom_metadata/relative_soup.dart',
|
||||
assetId: new AssetId('soup', 'lib/relative_soup.dart'),
|
||||
customDescriptors: [
|
||||
const ClassDescriptor('Soup', 'package:soup/annotations/soup.dart',
|
||||
superClass: 'Component'),
|
||||
]);
|
||||
const ClassDescriptor('Soup', 'package:soup/annotations/soup.dart',
|
||||
superClass: 'Component'),
|
||||
]);
|
||||
|
||||
_testNgDeps('Requires the specified import.', 'custom_metadata/bad_soup.dart',
|
||||
_testProcessor(
|
||||
'Requires the specified import.', 'custom_metadata/bad_soup.dart',
|
||||
customDescriptors: [
|
||||
const ClassDescriptor('Soup', 'package:soup/soup.dart',
|
||||
superClass: 'Component'),
|
||||
]);
|
||||
|
||||
_testNgDeps(
|
||||
_testProcessor(
|
||||
'should inline `templateUrl` values.', 'url_expression_files/hello.dart');
|
||||
|
||||
var absoluteReader = new TestAssetReader();
|
||||
absoluteReader.addAsset(new AssetId('other_package', 'lib/template.html'),
|
||||
absoluteReader.addAsset(
|
||||
new AssetId('other_package', 'lib/template.html'),
|
||||
readFile(
|
||||
'directive_processor/absolute_url_expression_files/template.html'));
|
||||
absoluteReader.addAsset(new AssetId('other_package', 'lib/template.css'),
|
||||
absoluteReader.addAsset(
|
||||
new AssetId('other_package', 'lib/template.css'),
|
||||
readFile(
|
||||
'directive_processor/absolute_url_expression_files/template.css'));
|
||||
_testNgDeps('should inline `templateUrl` and `styleUrls` values expressed as'
|
||||
' absolute urls.', 'absolute_url_expression_files/hello.dart',
|
||||
_testProcessor(
|
||||
'should inline `templateUrl` and `styleUrls` values expressed'
|
||||
' as absolute urls.',
|
||||
'absolute_url_expression_files/hello.dart',
|
||||
reader: absoluteReader);
|
||||
|
||||
_testNgDeps(
|
||||
_testProcessor(
|
||||
'should inline multiple `styleUrls` values expressed as absolute urls.',
|
||||
'multiple_style_urls_files/hello.dart');
|
||||
|
||||
@@ -64,40 +72,44 @@ void allTests() {
|
||||
readFile('directive_processor/multiple_style_urls_files/template.html'));
|
||||
absoluteReader.addAsset(new AssetId('a', 'lib/template.css'),
|
||||
readFile('directive_processor/multiple_style_urls_files/template.css'));
|
||||
absoluteReader.addAsset(new AssetId('a', 'lib/template_other.css'), readFile(
|
||||
'directive_processor/multiple_style_urls_files/template_other.css'));
|
||||
_testNgDeps(
|
||||
absoluteReader.addAsset(
|
||||
new AssetId('a', 'lib/template_other.css'),
|
||||
readFile(
|
||||
'directive_processor/multiple_style_urls_files/template_other.css'));
|
||||
_testProcessor(
|
||||
'shouldn\'t inline multiple `styleUrls` values expressed as absolute '
|
||||
'urls.', 'multiple_style_urls_not_inlined_files/hello.dart',
|
||||
inlineViews: false, reader: absoluteReader);
|
||||
'urls.',
|
||||
'multiple_style_urls_not_inlined_files/hello.dart',
|
||||
inlineViews: false,
|
||||
reader: absoluteReader);
|
||||
|
||||
_testNgDeps('should inline `templateUrl`s expressed as adjacent strings.',
|
||||
_testProcessor('should inline `templateUrl`s expressed as adjacent strings.',
|
||||
'split_url_expression_files/hello.dart');
|
||||
|
||||
_testNgDeps('should report implemented types as `interfaces`.',
|
||||
_testProcessor('should report implemented types as `interfaces`.',
|
||||
'interfaces_files/soup.dart');
|
||||
|
||||
_testNgDeps('should not include transitively implemented types.',
|
||||
_testProcessor('should not include transitively implemented types.',
|
||||
'interface_chain_files/soup.dart');
|
||||
|
||||
_testNgDeps('should not include superclasses in `interfaces`.',
|
||||
_testProcessor('should not include superclasses in `interfaces`.',
|
||||
'superclass_files/soup.dart');
|
||||
|
||||
_testNgDeps(
|
||||
_testProcessor(
|
||||
'should populate `lifecycle` when lifecycle interfaces are present.',
|
||||
'interface_lifecycle_files/soup.dart');
|
||||
|
||||
_testNgDeps('should populate multiple `lifecycle` values when necessary.',
|
||||
_testProcessor('should populate multiple `lifecycle` values when necessary.',
|
||||
'multiple_interface_lifecycle_files/soup.dart');
|
||||
|
||||
_testNgDeps(
|
||||
_testProcessor(
|
||||
'should populate `lifecycle` when lifecycle superclass is present.',
|
||||
'superclass_lifecycle_files/soup.dart');
|
||||
|
||||
_testNgDeps('should populate `lifecycle` with prefix when necessary.',
|
||||
_testProcessor('should populate `lifecycle` with prefix when necessary.',
|
||||
'prefixed_interface_lifecycle_files/soup.dart');
|
||||
|
||||
_testNgDeps(
|
||||
_testProcessor(
|
||||
'should not throw/hang on invalid urls', 'invalid_url_files/hello.dart',
|
||||
expectedLogs: [
|
||||
'ERROR: Uri /bad/absolute/url.html not supported from angular2|test/'
|
||||
@@ -110,13 +122,20 @@ void allTests() {
|
||||
'test/transform/directive_processor/invalid_url_files/hello.dart'
|
||||
]);
|
||||
|
||||
_testNgDeps('should find and register static functions.',
|
||||
_testProcessor('should find and register static functions.',
|
||||
'static_function_files/hello.dart');
|
||||
|
||||
_testProcessor('should find direcive aliases patterns.',
|
||||
'directive_aliases_files/hello.dart',
|
||||
reader: absoluteReader);
|
||||
}
|
||||
|
||||
void _testNgDeps(String name, String inputPath,
|
||||
{List<AnnotationDescriptor> customDescriptors: const [], AssetId assetId,
|
||||
AssetReader reader, List<String> expectedLogs, bool inlineViews: true,
|
||||
void _testProcessor(String name, String inputPath,
|
||||
{List<AnnotationDescriptor> customDescriptors: const [],
|
||||
AssetId assetId,
|
||||
AssetReader reader,
|
||||
List<String> expectedLogs,
|
||||
bool inlineViews: true,
|
||||
bool isolate: false}) {
|
||||
var testFn = isolate ? iit : it;
|
||||
testFn(name, () async {
|
||||
@@ -130,20 +149,33 @@ void _testNgDeps(String name, String inputPath,
|
||||
reader.addAsset(assetId, await reader.readAsString(inputId));
|
||||
inputId = assetId;
|
||||
}
|
||||
var expectedPath = path.join(path.dirname(inputPath), 'expected',
|
||||
var expectedNgDepsPath = path.join(path.dirname(inputPath), 'expected',
|
||||
path.basename(inputPath).replaceFirst('.dart', '.ng_deps.dart'));
|
||||
var expectedId = _assetIdForPath(expectedPath);
|
||||
var expectedNgDepsId = _assetIdForPath(expectedNgDepsPath);
|
||||
|
||||
var expectedAliasesPath = path.join(path.dirname(inputPath), 'expected',
|
||||
path.basename(inputPath).replaceFirst('.dart', '.aliases.json'));
|
||||
var expectedAliasesId = _assetIdForPath(expectedAliasesPath);
|
||||
|
||||
var annotationMatcher = new AnnotationMatcher()
|
||||
..addAll(customDescriptors);
|
||||
var output = await createNgDeps(reader, inputId, annotationMatcher,
|
||||
var ngMeta = new NgMeta.empty();
|
||||
var output = await createNgDeps(
|
||||
reader, inputId, annotationMatcher, ngMeta,
|
||||
inlineViews: inlineViews);
|
||||
if (output == null) {
|
||||
expect(await reader.hasInput(expectedId)).toBeFalse();
|
||||
expect(await reader.hasInput(expectedNgDepsId)).toBeFalse();
|
||||
} else {
|
||||
var input = await reader.readAsString(expectedId);
|
||||
var input = await reader.readAsString(expectedNgDepsId);
|
||||
expect(formatter.format(output)).toEqual(formatter.format(input));
|
||||
}
|
||||
if (ngMeta.isEmpty) {
|
||||
expect(await reader.hasInput(expectedAliasesId)).toBeFalse();
|
||||
} else {
|
||||
var expectedJson = await reader.readAsString(expectedAliasesId);
|
||||
expect(new JsonEncoder.withIndent(' ').convert(ngMeta.toJson()))
|
||||
.toEqual(expectedJson.trim());
|
||||
}
|
||||
});
|
||||
|
||||
if (expectedLogs != null) {
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
class Bar {}
|
||||
|
||||
const alias3 = const [Bar];
|
||||
@@ -0,0 +1 @@
|
||||
class Baz {}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"alias1": {
|
||||
"kind": "alias",
|
||||
"value": [
|
||||
"HelloCmp"
|
||||
]
|
||||
},
|
||||
"alias2": {
|
||||
"kind": "alias",
|
||||
"value": [
|
||||
"HelloCmp",
|
||||
"Foo"
|
||||
]
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
library examples.src.hello_world.absolute_url_expression_files.ng_deps.dart;
|
||||
|
||||
import 'hello.dart';
|
||||
export 'hello.dart';
|
||||
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
|
||||
import 'package:angular2/angular2.dart'
|
||||
show bootstrap, Component, Directive, View, NgElement;
|
||||
export 'a.dart' show alias3;
|
||||
import 'b.dart' as b;
|
||||
|
||||
var _visited = false;
|
||||
void initReflector() {
|
||||
if (_visited) return;
|
||||
_visited = true;
|
||||
_ngRef.reflector
|
||||
..registerType(HelloCmp, {
|
||||
'factory': () => new HelloCmp(),
|
||||
'parameters': const [],
|
||||
'annotations': const [
|
||||
const Component(selector: 'hello-app'),
|
||||
const View(
|
||||
template: r'''{{greeting}}''',
|
||||
templateUrl: r'template.html',
|
||||
styles: const [r'''.greeting { .color: blue; }''',])
|
||||
]
|
||||
});
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
library examples.src.hello_world.absolute_url_expression_files;
|
||||
|
||||
import 'package:angular2/angular2.dart'
|
||||
show bootstrap, Component, Directive, View, NgElement;
|
||||
export 'a.dart' show alias3;
|
||||
import 'b.dart' as b;
|
||||
|
||||
@Component(selector: 'hello-app')
|
||||
@View(templateUrl: 'template.html', styleUrls: const ['template.css'])
|
||||
class HelloCmp {}
|
||||
|
||||
class Foo {}
|
||||
|
||||
// valid
|
||||
const alias1 = const [HelloCmp];
|
||||
// valid, even though it includes things that are not components
|
||||
const alias2 = const [HelloCmp, Foo];
|
||||
|
||||
// Prefixed names are not supported
|
||||
const alias4 = const [b.Baz];
|
||||
+1
@@ -0,0 +1 @@
|
||||
.greeting { .color: blue; }
|
||||
+1
@@ -0,0 +1 @@
|
||||
{{greeting}}
|
||||
+23
-20
@@ -1,23 +1,26 @@
|
||||
{
|
||||
"MyComponent": {
|
||||
"id": "MyComponent",
|
||||
"selector": "[soup]",
|
||||
"compileChildren": true,
|
||||
"hostProperties": {},
|
||||
"hostListeners": {},
|
||||
"hostActions": {},
|
||||
"hostAttributes": {},
|
||||
"properties": [],
|
||||
"readAttributes": [],
|
||||
"type": 1,
|
||||
"exportAs": null,
|
||||
"callOnDestroy": false,
|
||||
"callOnCheck": false,
|
||||
"callOnInit": false,
|
||||
"callOnChange": false,
|
||||
"callOnAllChangesDone": false,
|
||||
"events": [],
|
||||
"changeDetection": null,
|
||||
"version": 1
|
||||
"kind": "type",
|
||||
"value": {
|
||||
"id": "MyComponent",
|
||||
"selector": "[soup]",
|
||||
"compileChildren": true,
|
||||
"hostProperties": {},
|
||||
"hostListeners": {},
|
||||
"hostActions": {},
|
||||
"hostAttributes": {},
|
||||
"properties": [],
|
||||
"readAttributes": [],
|
||||
"type": 1,
|
||||
"exportAs": null,
|
||||
"callOnDestroy": false,
|
||||
"callOnCheck": false,
|
||||
"callOnInit": false,
|
||||
"callOnChange": false,
|
||||
"callOnAllChangesDone": false,
|
||||
"events": [],
|
||||
"changeDetection": null,
|
||||
"version": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,21 @@ void changeDetectorTests() {
|
||||
var output = await (process(new AssetId('a', inputPath)));
|
||||
expect(output).toContain('notifyOnBinding');
|
||||
});
|
||||
|
||||
it('should include directives mentioned in directive aliases.', () async {
|
||||
// Input 2 is the same as input1, but contains the directive aliases
|
||||
// inlined.
|
||||
var input1Path =
|
||||
'template_compiler/directive_aliases_files/hello1.ng_deps.dart';
|
||||
var input2Path =
|
||||
'template_compiler/directive_aliases_files/hello2.ng_deps.dart';
|
||||
// Except for the directive argument in the View annotation, the generated
|
||||
// change detectors are identical.
|
||||
var output1 = (await process(new AssetId('a', input1Path))).replaceFirst(
|
||||
'directives: const [alias1]', 'directives: const [GoodbyeCmp]');
|
||||
var output2 = await process(new AssetId('a', input2Path));
|
||||
_formatThenExpectEquals(output1, output2);
|
||||
});
|
||||
}
|
||||
|
||||
void noChangeDetectorTests() {
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
library examples.hello_world.index_common_dart.ng_deps.dart;
|
||||
|
||||
import 'hello.dart';
|
||||
import 'package:angular2/angular2.dart'
|
||||
show bootstrap, Component, Directive, View, NgElement;
|
||||
|
||||
var _visited = false;
|
||||
void initReflector(reflector) {
|
||||
if (_visited) return;
|
||||
_visited = true;
|
||||
reflector
|
||||
..registerType(HelloCmp, {
|
||||
'factory': () => new HelloCmp(),
|
||||
'parameters': const [const []],
|
||||
'annotations': const [
|
||||
const Component(selector: 'hello-app'),
|
||||
const View(template: 'goodbye-app', directives: const [alias1])
|
||||
]
|
||||
})
|
||||
..registerType(GoodbyeCmp, {
|
||||
'factory': () => new GoodbyeCmp(),
|
||||
'parameters': const [const []],
|
||||
'annotations': const [
|
||||
const Component(selector: 'goodbye-app'),
|
||||
const View(template: 'Goodbye')
|
||||
]
|
||||
});
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"HelloCmp":
|
||||
{
|
||||
"kind": "type",
|
||||
"value": {
|
||||
"id":"HelloCmp",
|
||||
"selector":"hello-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
}
|
||||
},
|
||||
"GoodbyeCmp":{
|
||||
"kind": "type",
|
||||
"value": {
|
||||
"id":"GoodbyeCmp",
|
||||
"selector":"goodbye-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
}
|
||||
},
|
||||
"aliases1":{
|
||||
"kind": "alias",
|
||||
"value": [
|
||||
"GoodbyeCmp"
|
||||
]
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
library examples.hello_world.index_common_dart.ng_deps.dart;
|
||||
|
||||
import 'hello.dart';
|
||||
import 'package:angular2/angular2.dart'
|
||||
show bootstrap, Component, Directive, View, NgElement;
|
||||
|
||||
var _visited = false;
|
||||
void initReflector(reflector) {
|
||||
if (_visited) return;
|
||||
_visited = true;
|
||||
reflector
|
||||
..registerType(HelloCmp, {
|
||||
'factory': () => new HelloCmp(),
|
||||
'parameters': const [const []],
|
||||
'annotations': const [
|
||||
const Component(selector: 'hello-app'),
|
||||
const View(template: 'goodbye-app', directives: const [GoodbyeCmp])
|
||||
]
|
||||
})
|
||||
..registerType(GoodbyeCmp, {
|
||||
'factory': () => new GoodbyeCmp(),
|
||||
'parameters': const [const []],
|
||||
'annotations': const [
|
||||
const Component(selector: 'goodbye-app'),
|
||||
const View(template: 'Goodbye')
|
||||
]
|
||||
});
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"HelloCmp":
|
||||
{
|
||||
"kind": "type",
|
||||
"value": {
|
||||
"id":"HelloCmp",
|
||||
"selector":"hello-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
}
|
||||
},
|
||||
"GoodbyeCmp":{
|
||||
"kind": "type",
|
||||
"value": {
|
||||
"id":"GoodbyeCmp",
|
||||
"selector":"goodbye-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-9
@@ -1,13 +1,16 @@
|
||||
{
|
||||
"HelloCmp":
|
||||
{
|
||||
"id":"HelloCmp",
|
||||
"selector":"hello-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
"kind": "type",
|
||||
"value": {
|
||||
"id":"HelloCmp",
|
||||
"selector":"hello-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-9
@@ -1,13 +1,16 @@
|
||||
{
|
||||
"HelloCmp":
|
||||
{
|
||||
"id":"HelloCmp",
|
||||
"selector":"hello-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
"kind": "type",
|
||||
"value": {
|
||||
"id":"HelloCmp",
|
||||
"selector":"hello-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-9
@@ -1,13 +1,16 @@
|
||||
{
|
||||
"HelloCmp":
|
||||
{
|
||||
"id":"HelloCmp",
|
||||
"selector":"hello-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
"kind": "type",
|
||||
"value": {
|
||||
"id":"HelloCmp",
|
||||
"selector":"hello-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
{
|
||||
"HelloCmp":
|
||||
{
|
||||
"id":"HelloCmp",
|
||||
"selector":"hello-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
"kind": "type",
|
||||
"value": {
|
||||
"id":"HelloCmp",
|
||||
"selector":"hello-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+23
-17
@@ -1,23 +1,29 @@
|
||||
{
|
||||
"HelloCmp":
|
||||
{
|
||||
"id":"HelloCmp",
|
||||
"selector":"hello-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
"kind": "type",
|
||||
"value": {
|
||||
"id":"HelloCmp",
|
||||
"selector":"hello-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
}
|
||||
},
|
||||
"GoodbyeCmp":{
|
||||
"id":"GoodbyeCmp",
|
||||
"selector":"goodbye-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
"kind": "type",
|
||||
"value": {
|
||||
"id":"GoodbyeCmp",
|
||||
"selector":"goodbye-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-9
@@ -1,13 +1,16 @@
|
||||
{
|
||||
"HelloCmp":
|
||||
{
|
||||
"id":"HelloCmp",
|
||||
"selector":"hello-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
"kind": "type",
|
||||
"value": {
|
||||
"id":"HelloCmp",
|
||||
"selector":"hello-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-9
@@ -1,13 +1,16 @@
|
||||
{
|
||||
"HelloCmp":
|
||||
{
|
||||
"id":"HelloCmp",
|
||||
"selector":"hello-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
"kind": "type",
|
||||
"value": {
|
||||
"id":"HelloCmp",
|
||||
"selector":"hello-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-9
@@ -1,12 +1,15 @@
|
||||
{
|
||||
"GoodbyeCmp":{
|
||||
"id":"GoodbyeCmp",
|
||||
"selector":"goodbye-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
"kind": "type",
|
||||
"value": {
|
||||
"id":"GoodbyeCmp",
|
||||
"selector":"goodbye-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-9
@@ -1,13 +1,16 @@
|
||||
{
|
||||
"HelloCmp":
|
||||
{
|
||||
"id":"HelloCmp",
|
||||
"selector":"hello-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
"kind": "type",
|
||||
"value": {
|
||||
"id":"HelloCmp",
|
||||
"selector":"hello-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-8
@@ -1,12 +1,15 @@
|
||||
{
|
||||
"MyApp":{
|
||||
"id":"MyApp",
|
||||
"selector":"my-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
"kind": "type",
|
||||
"value": {
|
||||
"id":"MyApp",
|
||||
"selector":"my-app",
|
||||
"compileChildren":true,
|
||||
"host":{},
|
||||
"properties":[],
|
||||
"readAttributes":[],
|
||||
"type":1,
|
||||
"version":1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:unittest/unittest.dart' hide expect;
|
||||
import 'package:unittest/vm_config.dart';
|
||||
|
||||
import 'common/async_string_writer_tests.dart' as asyncStringWriter;
|
||||
import 'common/ng_meta_test.dart' as ngMetaTest;
|
||||
import 'bind_generator/all_tests.dart' as bindGenerator;
|
||||
import 'deferred_rewriter/all_tests.dart' as deferredRewriter;
|
||||
import 'directive_linker/all_tests.dart' as directiveLinker;
|
||||
@@ -17,6 +18,7 @@ import 'template_compiler/all_tests.dart' as templateCompiler;
|
||||
main() {
|
||||
useVMConfiguration();
|
||||
describe('AsyncStringWriter', asyncStringWriter.allTests);
|
||||
describe('NgMeta', ngMetaTest.allTests);
|
||||
describe('Bind Generator', bindGenerator.allTests);
|
||||
describe('Directive Linker', directiveLinker.allTests);
|
||||
describe('Directive Metadata Extractor', directiveMeta.allTests);
|
||||
|
||||
Reference in New Issue
Block a user