Skip to content

Commit 583a0c3

Browse files
committed
Add tests to validate behavior of configuration support
1 parent 4976682 commit 583a0c3

File tree

6 files changed

+369
-0
lines changed

6 files changed

+369
-0
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
builders:
2+
scss_builder:
3+
target: "scss_builder"
4+
import: "package:angular_components/builder.dart"
5+
builder_factories: ["scssBuilder"]
6+
build_to: cache
7+
build_extensions:
8+
.scss: [".scss.css"]
9+
.sass: [".scss.css"]
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
builders:
2+
angular:
3+
import: "package:angular/builder.dart"
4+
builder_factories:
5+
- templatePlaceholder
6+
- templateCompiler
7+
- stylesheetCompiler
8+
auto_apply: none
9+
applies_builders:
10+
- "angular|placeholder_cleanup"
11+
- "angular|component_source_cleanup"
12+
# See https://github.com/dart-lang/angular/issues/988.
13+
is_optional: true
14+
required_inputs:
15+
- ".css"
16+
build_extensions:
17+
.css:
18+
- ".css.dart"
19+
- ".css.shim.dart"
20+
.dart:
21+
- ".template.dart"
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
// ignore_for_file: annotate_overrides
6+
7+
import 'package:json_annotation/json_annotation.dart';
8+
import 'package:meta/meta.dart';
9+
10+
part 'build_config.g.dart';
11+
12+
@JsonSerializable()
13+
class Config extends Object with _$ConfigSerializerMixin {
14+
final Map<String, Builder> builders;
15+
16+
Config({@required this.builders});
17+
18+
factory Config.fromJson(Map map) => _$ConfigFromJson(map);
19+
}
20+
21+
@JsonSerializable(includeIfNull: false)
22+
class Builder extends Object with _$BuilderSerializerMixin {
23+
@JsonKey(nullable: true)
24+
final String target;
25+
final String import;
26+
27+
@JsonKey(name: 'is_optional')
28+
final bool isOptional;
29+
30+
@JsonKey(name: 'auto_apply', toJson: _toJson, fromJson: _fromJson)
31+
final AutoApply autoApply;
32+
33+
@JsonKey(name: 'builder_factories', nullable: false)
34+
final List<String> builderFactories;
35+
36+
@JsonKey(name: 'applies_builders')
37+
final List<String> appliesBuilders;
38+
39+
@JsonKey(name: 'required_inputs')
40+
final List<String> requiredInputs;
41+
42+
@JsonKey(name: 'build_extensions')
43+
final Map<String, List<String>> buildExtentions;
44+
45+
Builder({
46+
@required this.import,
47+
this.target,
48+
this.isOptional,
49+
this.autoApply,
50+
this.builderFactories,
51+
this.appliesBuilders,
52+
this.requiredInputs,
53+
this.buildExtentions,
54+
}) {
55+
if (builderFactories.isEmpty) {
56+
throw new ArgumentError.value(builderFactories, 'builderFactories',
57+
'Must have at least one value.');
58+
}
59+
}
60+
61+
factory Builder.fromJson(Map map) => _$BuilderFromJson(map);
62+
}
63+
64+
enum AutoApply { none, dependents, allPackages, rootPackage }
65+
66+
//TODO: remove all of this and annotate the fields on the enum once we have
67+
//pkg:analyzer with github.com/dart-lang/sdk/commit/74db253d34
68+
AutoApply _fromJson(String input) {
69+
var value = _autoApplyConvert[input];
70+
if (value == null) {
71+
var allowed = _autoApplyConvert.keys.map((e) => '"$e"').join(', ');
72+
throw new ArgumentError.value(
73+
input, 'autoApply', '"$input" is not in the supported set: $allowed.');
74+
}
75+
return value;
76+
}
77+
78+
String _toJson(AutoApply value) {
79+
if (value == null) {
80+
return null;
81+
}
82+
var string = _autoApplyConvert.entries
83+
.singleWhere((e) => e.value == value, orElse: () => null)
84+
?.key;
85+
86+
if (string == null) {
87+
throw new ArgumentError.value(value, 'autoApply', 'Unsupported value.');
88+
}
89+
return string;
90+
}
91+
92+
const _autoApplyConvert = const {
93+
'none': AutoApply.none,
94+
'dependents': AutoApply.dependents,
95+
'all_packages': AutoApply.allPackages,
96+
'root_package': AutoApply.rootPackage
97+
};
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
// GENERATED CODE - DO NOT MODIFY BY HAND
6+
7+
part of 'build_config.dart';
8+
9+
// **************************************************************************
10+
// Generator: JsonSerializableGenerator
11+
// **************************************************************************
12+
13+
Config _$ConfigFromJson(Map json) => $checkedNew(
14+
'Config',
15+
json,
16+
const {'builders': 'builders'},
17+
() => new Config(
18+
builders: $checkedConvert(
19+
json,
20+
'builders',
21+
() => (json['builders'] as Map)?.map((k, e) => new MapEntry(
22+
k as String,
23+
e == null ? null : new Builder.fromJson(e as Map))))));
24+
25+
abstract class _$ConfigSerializerMixin {
26+
Map<String, Builder> get builders;
27+
Map<String, dynamic> toJson() => <String, dynamic>{'builders': builders};
28+
}
29+
30+
Builder _$BuilderFromJson(Map json) => $checkedNew(
31+
'Builder',
32+
json,
33+
const {
34+
'import': 'import',
35+
'target': 'target',
36+
'isOptional': 'is_optional',
37+
'autoApply': 'auto_apply',
38+
'builderFactories': 'builder_factories',
39+
'appliesBuilders': 'applies_builders',
40+
'requiredInputs': 'required_inputs',
41+
'buildExtentions': 'build_extensions'
42+
},
43+
() => new Builder(
44+
import: $checkedConvert(json, 'import', () => json['import'] as String),
45+
target: $checkedConvert(json, 'target', () => json['target'] as String),
46+
isOptional: $checkedConvert(
47+
json, 'is_optional', () => json['is_optional'] as bool),
48+
autoApply: $checkedConvert(
49+
json,
50+
'auto_apply',
51+
() => json['auto_apply'] == null
52+
? null
53+
: _fromJson(json['auto_apply'] as String)),
54+
builderFactories: $checkedConvert(
55+
json,
56+
'builder_factories',
57+
() => (json['builder_factories'] as List)
58+
.map((e) => e as String)
59+
.toList()),
60+
appliesBuilders: $checkedConvert(
61+
json,
62+
'applies_builders',
63+
() => (json['applies_builders'] as List)
64+
?.map((e) => e as String)
65+
?.toList()),
66+
requiredInputs: $checkedConvert(
67+
json,
68+
'required_inputs',
69+
() => (json['required_inputs'] as List)
70+
?.map((e) => e as String)
71+
?.toList()),
72+
buildExtentions: $checkedConvert(
73+
json,
74+
'build_extensions',
75+
() => (json['build_extensions'] as Map)?.map((k, e) => new MapEntry(
76+
k as String,
77+
(e as List)?.map((e) => e as String)?.toList())))));
78+
79+
abstract class _$BuilderSerializerMixin {
80+
String get target;
81+
String get import;
82+
bool get isOptional;
83+
AutoApply get autoApply;
84+
List<String> get builderFactories;
85+
List<String> get appliesBuilders;
86+
List<String> get requiredInputs;
87+
Map<String, List<String>> get buildExtentions;
88+
Map<String, dynamic> toJson() {
89+
var val = <String, dynamic>{};
90+
91+
void writeNotNull(String key, dynamic value) {
92+
if (value != null) {
93+
val[key] = value;
94+
}
95+
}
96+
97+
writeNotNull('target', target);
98+
writeNotNull('import', import);
99+
writeNotNull('is_optional', isOptional);
100+
writeNotNull('auto_apply', autoApply == null ? null : _toJson(autoApply));
101+
val['builder_factories'] = builderFactories;
102+
writeNotNull('applies_builders', appliesBuilders);
103+
writeNotNull('required_inputs', requiredInputs);
104+
writeNotNull('build_extensions', buildExtentions);
105+
return val;
106+
}
107+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
builders:
2+
# The regular builder config, creates `.tar.gz` files.
3+
regular_builder:
4+
import: "package:my_package/builder.dart"
5+
builder_factories: ["myBuilder"]
6+
build_extensions: {".dart": [".tar.gz"]}
7+
auto_apply: root_package
8+
apply_builders: ["|archive_extract_builder"]

json_serializable/test/yaml_test.dart

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:io';
6+
7+
import 'package:json_annotation/json_annotation.dart';
8+
import 'package:path/path.dart' as p;
9+
import 'package:test/test.dart';
10+
import 'package:yaml/yaml.dart';
11+
12+
import 'config/build_config.dart';
13+
14+
import 'test_utils.dart';
15+
16+
final _root = p.join('test', 'config');
17+
18+
List<String> _getTests() => new Directory(_root)
19+
.listSync()
20+
.where((fse) => fse is File && p.extension(fse.path) == '.yaml')
21+
.map((fse) => fse.path)
22+
.toList();
23+
24+
void main() {
25+
group('valid configurations', () {
26+
for (var filePath in _getTests()) {
27+
test(p.basenameWithoutExtension(filePath), () {
28+
var content = new File(filePath).readAsStringSync();
29+
var yamlContent = loadYaml(content, sourceUrl: filePath) as YamlMap;
30+
31+
try {
32+
var config = new Config.fromJson(yamlContent);
33+
expect(config, isNotNull);
34+
} on CheckedFromJsonException catch (e) {
35+
print(_prettyPrintCheckedFromJsonException(e));
36+
rethrow;
37+
}
38+
});
39+
}
40+
});
41+
42+
group('bad configs', () {
43+
var index = 0;
44+
for (var entry in _badConfigs.entries) {
45+
test('${index++}', () {
46+
var yamlContent =
47+
loadYaml(entry.key, sourceUrl: 'file.yaml') as YamlMap;
48+
49+
expect(yamlContent, isNotNull);
50+
printOnFailure(entry.key);
51+
52+
try {
53+
var config = new Config.fromJson(yamlContent);
54+
print(loudEncode(config));
55+
fail('parse should fail');
56+
} on CheckedFromJsonException catch (e) {
57+
var prettyOutput = _prettyPrintCheckedFromJsonException(e);
58+
printOnFailure(prettyOutput);
59+
expect(prettyOutput, entry.value);
60+
}
61+
});
62+
}
63+
});
64+
}
65+
66+
final _badConfigs = const {
67+
r'''
68+
builders:
69+
- a
70+
- b
71+
''': r'''
72+
line 1, column 1 of file.yaml: Could not create `Config`. Unsupported value for `builders`.
73+
builders:
74+
^^^^^^^^''',
75+
r'''
76+
builders:
77+
a:
78+
target: 42
79+
''': r'''
80+
line 3, column 5 of file.yaml: Could not create `Builder`. Unsupported value for `target`.
81+
target: 42
82+
^^^^^^''',
83+
r'''
84+
builders:
85+
a:
86+
target: "a target"
87+
auto_apply: unsupported
88+
''': r'''
89+
line 4, column 5 of file.yaml: Could not create `Builder`. Unsupported value for `auto_apply`. "unsupported" is not in the supported set: "none", "dependents", "all_packages", "root_package".
90+
auto_apply: unsupported
91+
^^^^^^^^^^''',
92+
r'''
93+
builders:
94+
a:
95+
builder_factories: []
96+
''': r'''
97+
line 3, column 5 of file.yaml: Could not create `Builder`. Unsupported value for `builder_factories`. Must have at least one value.
98+
builder_factories: []
99+
^^^^^^^^^^^^^^^^^''',
100+
};
101+
102+
String _prettyPrintCheckedFromJsonException(CheckedFromJsonException err) {
103+
var yamlMap = err.map as YamlMap;
104+
105+
var yamlKey = yamlMap.nodes.keys.singleWhere(
106+
(k) => (k as YamlScalar).value == err.key,
107+
orElse: () => null) as YamlScalar;
108+
109+
var message = 'Could not create `${err.className}`.';
110+
if (yamlKey == null) {
111+
assert(err.key == null);
112+
message = [yamlMap.span.message(message), err.innerError].join('\n');
113+
} else {
114+
message = '$message Unsupported value for `${err.key}`.';
115+
116+
if (err.targetType != dynamic &&
117+
(err.innerError is CastError || err.innerError is TypeError)) {
118+
message = '$message Could not convert to `${err.targetType}`.';
119+
} else if (err.message != null) {
120+
message = '$message ${err.message}';
121+
}
122+
123+
message = yamlKey.span.message(message);
124+
}
125+
126+
return message;
127+
}

0 commit comments

Comments
 (0)